1*18c2aff7Sartem /* 2*18c2aff7Sartem * CDDL HEADER START 3*18c2aff7Sartem * 4*18c2aff7Sartem * The contents of this file are subject to the terms of the 5*18c2aff7Sartem * Common Development and Distribution License (the "License"). 6*18c2aff7Sartem * You may not use this file except in compliance with the License. 7*18c2aff7Sartem * 8*18c2aff7Sartem * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*18c2aff7Sartem * or http://www.opensolaris.org/os/licensing. 10*18c2aff7Sartem * See the License for the specific language governing permissions 11*18c2aff7Sartem * and limitations under the License. 12*18c2aff7Sartem * 13*18c2aff7Sartem * When distributing Covered Code, include this CDDL HEADER in each 14*18c2aff7Sartem * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*18c2aff7Sartem * If applicable, add the following below this CDDL HEADER, with the 16*18c2aff7Sartem * fields enclosed by brackets "[]" replaced with your own identifying 17*18c2aff7Sartem * information: Portions Copyright [yyyy] [name of copyright owner] 18*18c2aff7Sartem * 19*18c2aff7Sartem * CDDL HEADER END 20*18c2aff7Sartem */ 21*18c2aff7Sartem /* 22*18c2aff7Sartem * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*18c2aff7Sartem * Use is subject to license terms. 24*18c2aff7Sartem */ 25*18c2aff7Sartem 26*18c2aff7Sartem #pragma ident "%Z%%M% %I% %E% SMI" 27*18c2aff7Sartem 28*18c2aff7Sartem #include <stdio.h> 29*18c2aff7Sartem #include <errno.h> 30*18c2aff7Sartem #include <string.h> 31*18c2aff7Sartem #include <strings.h> 32*18c2aff7Sartem #include <stdarg.h> 33*18c2aff7Sartem #include <fcntl.h> 34*18c2aff7Sartem #include <libintl.h> 35*18c2aff7Sartem #include <stdlib.h> 36*18c2aff7Sartem #include <unistd.h> 37*18c2aff7Sartem #include <ctype.h> 38*18c2aff7Sartem #include <sys/param.h> 39*18c2aff7Sartem #include <sys/types.h> 40*18c2aff7Sartem #include <sys/stat.h> 41*18c2aff7Sartem #include <sys/mnttab.h> 42*18c2aff7Sartem 43*18c2aff7Sartem #include <dbus/dbus.h> 44*18c2aff7Sartem #include <dbus/dbus-glib.h> 45*18c2aff7Sartem #include <dbus/dbus-glib-lowlevel.h> 46*18c2aff7Sartem #include <libhal.h> 47*18c2aff7Sartem #include <libhal-storage.h> 48*18c2aff7Sartem 49*18c2aff7Sartem #include "rmm_common.h" 50*18c2aff7Sartem 51*18c2aff7Sartem extern int rmm_debug; 52*18c2aff7Sartem 53*18c2aff7Sartem static const char *action_strings[] = { 54*18c2aff7Sartem "eject", 55*18c2aff7Sartem "mount", 56*18c2aff7Sartem "remount", 57*18c2aff7Sartem "unmount", 58*18c2aff7Sartem "clear_mounts", 59*18c2aff7Sartem "closetray" 60*18c2aff7Sartem }; 61*18c2aff7Sartem 62*18c2aff7Sartem 63*18c2aff7Sartem LibHalContext * 64*18c2aff7Sartem rmm_hal_init(LibHalDeviceAdded devadd_cb, LibHalDeviceRemoved devrem_cb, 65*18c2aff7Sartem LibHalDevicePropertyModified propmod_cb, 66*18c2aff7Sartem DBusError *error, rmm_error_t *rmm_error) 67*18c2aff7Sartem { 68*18c2aff7Sartem DBusConnection *dbus_conn; 69*18c2aff7Sartem LibHalContext *ctx; 70*18c2aff7Sartem char **devices; 71*18c2aff7Sartem int nr; 72*18c2aff7Sartem 73*18c2aff7Sartem dbus_error_init(error); 74*18c2aff7Sartem 75*18c2aff7Sartem /* 76*18c2aff7Sartem * setup D-Bus connection 77*18c2aff7Sartem */ 78*18c2aff7Sartem if (!(dbus_conn = dbus_bus_get(DBUS_BUS_SYSTEM, error))) { 79*18c2aff7Sartem dprintf("cannot get system bus: %s\n", rmm_strerror(error, -1)); 80*18c2aff7Sartem *rmm_error = RMM_EDBUS_CONNECT; 81*18c2aff7Sartem return (NULL); 82*18c2aff7Sartem } 83*18c2aff7Sartem rmm_dbus_error_free(error); 84*18c2aff7Sartem 85*18c2aff7Sartem dbus_connection_setup_with_g_main(dbus_conn, NULL); 86*18c2aff7Sartem dbus_connection_set_exit_on_disconnect(dbus_conn, B_TRUE); 87*18c2aff7Sartem 88*18c2aff7Sartem if ((ctx = libhal_ctx_new()) == NULL) { 89*18c2aff7Sartem dprintf("libhal_ctx_new failed"); 90*18c2aff7Sartem *rmm_error = RMM_EHAL_CONNECT; 91*18c2aff7Sartem return (NULL); 92*18c2aff7Sartem } 93*18c2aff7Sartem 94*18c2aff7Sartem libhal_ctx_set_dbus_connection(ctx, dbus_conn); 95*18c2aff7Sartem 96*18c2aff7Sartem /* 97*18c2aff7Sartem * register callbacks 98*18c2aff7Sartem */ 99*18c2aff7Sartem if (devadd_cb != NULL) { 100*18c2aff7Sartem libhal_ctx_set_device_added(ctx, devadd_cb); 101*18c2aff7Sartem } 102*18c2aff7Sartem if (devrem_cb != NULL) { 103*18c2aff7Sartem libhal_ctx_set_device_removed(ctx, devrem_cb); 104*18c2aff7Sartem } 105*18c2aff7Sartem if (propmod_cb != NULL) { 106*18c2aff7Sartem libhal_ctx_set_device_property_modified(ctx, propmod_cb); 107*18c2aff7Sartem if (!libhal_device_property_watch_all(ctx, error)) { 108*18c2aff7Sartem dprintf("property_watch_all failed %s", 109*18c2aff7Sartem rmm_strerror(error, -1)); 110*18c2aff7Sartem libhal_ctx_free(ctx); 111*18c2aff7Sartem *rmm_error = RMM_EHAL_CONNECT; 112*18c2aff7Sartem return (NULL); 113*18c2aff7Sartem } 114*18c2aff7Sartem } 115*18c2aff7Sartem 116*18c2aff7Sartem if (!libhal_ctx_init(ctx, error)) { 117*18c2aff7Sartem dprintf("libhal_ctx_init failed: %s", rmm_strerror(error, -1)); 118*18c2aff7Sartem libhal_ctx_free(ctx); 119*18c2aff7Sartem *rmm_error = RMM_EHAL_CONNECT; 120*18c2aff7Sartem return (NULL); 121*18c2aff7Sartem } 122*18c2aff7Sartem rmm_dbus_error_free(error); 123*18c2aff7Sartem 124*18c2aff7Sartem /* 125*18c2aff7Sartem * The above functions do not guarantee that HAL is actually running. 126*18c2aff7Sartem * Check by invoking a method. 127*18c2aff7Sartem */ 128*18c2aff7Sartem if (!(devices = libhal_get_all_devices(ctx, &nr, error))) { 129*18c2aff7Sartem dprintf("HAL is not running: %s", rmm_strerror(error, -1)); 130*18c2aff7Sartem libhal_ctx_shutdown(ctx, NULL); 131*18c2aff7Sartem libhal_ctx_free(ctx); 132*18c2aff7Sartem *rmm_error = RMM_EHAL_CONNECT; 133*18c2aff7Sartem return (NULL); 134*18c2aff7Sartem } else { 135*18c2aff7Sartem rmm_dbus_error_free(error); 136*18c2aff7Sartem libhal_free_string_array(devices); 137*18c2aff7Sartem } 138*18c2aff7Sartem 139*18c2aff7Sartem return (ctx); 140*18c2aff7Sartem } 141*18c2aff7Sartem 142*18c2aff7Sartem 143*18c2aff7Sartem void 144*18c2aff7Sartem rmm_hal_fini(LibHalContext *hal_ctx) 145*18c2aff7Sartem { 146*18c2aff7Sartem DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx); 147*18c2aff7Sartem 148*18c2aff7Sartem (void) dbus_connection_close(dbus_conn); 149*18c2aff7Sartem (void) libhal_ctx_free(hal_ctx); 150*18c2aff7Sartem } 151*18c2aff7Sartem 152*18c2aff7Sartem 153*18c2aff7Sartem /* 154*18c2aff7Sartem * find volume from any type of name, similar to the old media_findname() 155*18c2aff7Sartem * returns the LibHalDrive object and a list of LibHalVolume objects. 156*18c2aff7Sartem */ 157*18c2aff7Sartem LibHalDrive * 158*18c2aff7Sartem rmm_hal_volume_find(LibHalContext *hal_ctx, const char *name, DBusError *error, 159*18c2aff7Sartem GSList **volumes) 160*18c2aff7Sartem { 161*18c2aff7Sartem LibHalDrive *drive; 162*18c2aff7Sartem char *p; 163*18c2aff7Sartem char lastc; 164*18c2aff7Sartem 165*18c2aff7Sartem *volumes = NULL; 166*18c2aff7Sartem 167*18c2aff7Sartem /* temporarily remove trailing slash */ 168*18c2aff7Sartem p = (char *)name + strlen(name) - 1; 169*18c2aff7Sartem if (*p == '/') { 170*18c2aff7Sartem lastc = *p; 171*18c2aff7Sartem *p = '\0'; 172*18c2aff7Sartem } else { 173*18c2aff7Sartem p = NULL; 174*18c2aff7Sartem } 175*18c2aff7Sartem 176*18c2aff7Sartem if (name[0] == '/') { 177*18c2aff7Sartem if (((drive = rmm_hal_volume_findby(hal_ctx, 178*18c2aff7Sartem "info.udi", name, volumes)) != NULL) || 179*18c2aff7Sartem ((drive = rmm_hal_volume_findby(hal_ctx, 180*18c2aff7Sartem "block.device", name, volumes)) != NULL) || 181*18c2aff7Sartem ((drive = rmm_hal_volume_findby(hal_ctx, 182*18c2aff7Sartem "block.solaris.raw_device", name, volumes)) != NULL) || 183*18c2aff7Sartem ((drive = rmm_hal_volume_findby(hal_ctx, 184*18c2aff7Sartem "volume.mount_point", name, volumes)) != NULL)) { 185*18c2aff7Sartem goto out; 186*18c2aff7Sartem } else { 187*18c2aff7Sartem goto out; 188*18c2aff7Sartem } 189*18c2aff7Sartem } 190*18c2aff7Sartem 191*18c2aff7Sartem /* try volume label */ 192*18c2aff7Sartem if ((drive = rmm_hal_volume_findby(hal_ctx, 193*18c2aff7Sartem "volume.label", name, volumes)) != NULL) { 194*18c2aff7Sartem goto out; 195*18c2aff7Sartem } 196*18c2aff7Sartem 197*18c2aff7Sartem drive = rmm_hal_volume_findby_nickname(hal_ctx, name, volumes); 198*18c2aff7Sartem 199*18c2aff7Sartem out: 200*18c2aff7Sartem if (p != NULL) { 201*18c2aff7Sartem *p = lastc; 202*18c2aff7Sartem } 203*18c2aff7Sartem return (drive); 204*18c2aff7Sartem } 205*18c2aff7Sartem 206*18c2aff7Sartem /* 207*18c2aff7Sartem * find default volume. Returns volume pointer and name in 'name'. 208*18c2aff7Sartem */ 209*18c2aff7Sartem LibHalDrive * 210*18c2aff7Sartem rmm_hal_volume_find_default(LibHalContext *hal_ctx, DBusError *error, 211*18c2aff7Sartem const char **name_out, GSList **volumes) 212*18c2aff7Sartem { 213*18c2aff7Sartem LibHalDrive *drive; 214*18c2aff7Sartem static const char *names[] = { "floppy", "cdrom", "rmdisk" }; 215*18c2aff7Sartem int i; 216*18c2aff7Sartem 217*18c2aff7Sartem *volumes = NULL; 218*18c2aff7Sartem 219*18c2aff7Sartem for (i = 0; i < NELEM(names); i++) { 220*18c2aff7Sartem if ((drive = rmm_hal_volume_findby_nickname(hal_ctx, 221*18c2aff7Sartem names[i], volumes)) != NULL) { 222*18c2aff7Sartem /* 223*18c2aff7Sartem * Skip floppy if it has no media. 224*18c2aff7Sartem * XXX might want to actually check for media 225*18c2aff7Sartem * every time instead of relying on volcheck. 226*18c2aff7Sartem */ 227*18c2aff7Sartem if ((strcmp(names[i], "floppy") != 0) || 228*18c2aff7Sartem libhal_device_get_property_bool(hal_ctx, 229*18c2aff7Sartem libhal_drive_get_udi(drive), 230*18c2aff7Sartem "storage.removable.media_available", NULL)) { 231*18c2aff7Sartem *name_out = names[i]; 232*18c2aff7Sartem break; 233*18c2aff7Sartem } 234*18c2aff7Sartem } 235*18c2aff7Sartem rmm_dbus_error_free(error); 236*18c2aff7Sartem } 237*18c2aff7Sartem 238*18c2aff7Sartem return (drive); 239*18c2aff7Sartem } 240*18c2aff7Sartem 241*18c2aff7Sartem /* 242*18c2aff7Sartem * find volume by property=value 243*18c2aff7Sartem * returns the LibHalDrive object and a list of LibHalVolume objects. 244*18c2aff7Sartem * XXX add support for multiple properties, reduce D-Bus traffic 245*18c2aff7Sartem */ 246*18c2aff7Sartem LibHalDrive * 247*18c2aff7Sartem rmm_hal_volume_findby(LibHalContext *hal_ctx, const char *property, 248*18c2aff7Sartem const char *value, GSList **volumes) 249*18c2aff7Sartem { 250*18c2aff7Sartem DBusError error; 251*18c2aff7Sartem LibHalDrive *drive = NULL; 252*18c2aff7Sartem LibHalVolume *v = NULL; 253*18c2aff7Sartem char **udis; 254*18c2aff7Sartem int num_udis; 255*18c2aff7Sartem int i; 256*18c2aff7Sartem 257*18c2aff7Sartem *volumes = NULL; 258*18c2aff7Sartem 259*18c2aff7Sartem dbus_error_init(&error); 260*18c2aff7Sartem 261*18c2aff7Sartem /* get all devices with property=value */ 262*18c2aff7Sartem if ((udis = libhal_manager_find_device_string_match(hal_ctx, property, 263*18c2aff7Sartem value, &num_udis, &error)) == NULL) { 264*18c2aff7Sartem rmm_dbus_error_free(&error); 265*18c2aff7Sartem return (NULL); 266*18c2aff7Sartem } 267*18c2aff7Sartem 268*18c2aff7Sartem /* find volumes among these devices */ 269*18c2aff7Sartem for (i = 0; i < num_udis; i++) { 270*18c2aff7Sartem rmm_dbus_error_free(&error); 271*18c2aff7Sartem if (libhal_device_query_capability(hal_ctx, udis[i], "volume", 272*18c2aff7Sartem &error)) { 273*18c2aff7Sartem v = libhal_volume_from_udi(hal_ctx, udis[i]); 274*18c2aff7Sartem if (v != NULL) { 275*18c2aff7Sartem *volumes = g_slist_prepend(*volumes, v); 276*18c2aff7Sartem } 277*18c2aff7Sartem } 278*18c2aff7Sartem } 279*18c2aff7Sartem 280*18c2aff7Sartem /* used prepend, preserve original order */ 281*18c2aff7Sartem if (*volumes != NULL) { 282*18c2aff7Sartem *volumes = g_slist_reverse(*volumes); 283*18c2aff7Sartem 284*18c2aff7Sartem v = (LibHalVolume *)(*volumes)->data; 285*18c2aff7Sartem drive = libhal_drive_from_udi(hal_ctx, 286*18c2aff7Sartem libhal_volume_get_storage_device_udi(v)); 287*18c2aff7Sartem if (drive == NULL) { 288*18c2aff7Sartem rmm_volumes_free (*volumes); 289*18c2aff7Sartem *volumes = NULL; 290*18c2aff7Sartem } 291*18c2aff7Sartem } 292*18c2aff7Sartem 293*18c2aff7Sartem libhal_free_string_array(udis); 294*18c2aff7Sartem rmm_dbus_error_free(&error); 295*18c2aff7Sartem 296*18c2aff7Sartem return (drive); 297*18c2aff7Sartem } 298*18c2aff7Sartem 299*18c2aff7Sartem 300*18c2aff7Sartem /* 301*18c2aff7Sartem * print nicknames for each available volume 302*18c2aff7Sartem */ 303*18c2aff7Sartem void 304*18c2aff7Sartem rmm_print_volume_nicknames(LibHalContext *hal_ctx, DBusError *error) 305*18c2aff7Sartem { 306*18c2aff7Sartem char **udis; 307*18c2aff7Sartem int num_udis; 308*18c2aff7Sartem char *block_device; 309*18c2aff7Sartem char *drive_udi; 310*18c2aff7Sartem char *volume_label; 311*18c2aff7Sartem char *mount_point; 312*18c2aff7Sartem boolean_t comma; 313*18c2aff7Sartem char **nicknames; 314*18c2aff7Sartem int i, j; 315*18c2aff7Sartem 316*18c2aff7Sartem dbus_error_init(error); 317*18c2aff7Sartem 318*18c2aff7Sartem if ((udis = libhal_find_device_by_capability(hal_ctx, "volume", 319*18c2aff7Sartem &num_udis, error)) == NULL) { 320*18c2aff7Sartem return; 321*18c2aff7Sartem } 322*18c2aff7Sartem 323*18c2aff7Sartem for (i = 0; i < num_udis; i++) { 324*18c2aff7Sartem if ((block_device = libhal_device_get_property_string(hal_ctx, 325*18c2aff7Sartem udis[i], "block.device", NULL)) == NULL) { 326*18c2aff7Sartem continue; 327*18c2aff7Sartem } 328*18c2aff7Sartem if ((drive_udi = libhal_device_get_property_string(hal_ctx, 329*18c2aff7Sartem udis[i], "block.storage_device", NULL)) == NULL) { 330*18c2aff7Sartem libhal_free_string(block_device); 331*18c2aff7Sartem continue; 332*18c2aff7Sartem } 333*18c2aff7Sartem (void) printf("%s\t", block_device); 334*18c2aff7Sartem comma = B_FALSE; 335*18c2aff7Sartem 336*18c2aff7Sartem if ((nicknames = libhal_device_get_property_strlist(hal_ctx, 337*18c2aff7Sartem drive_udi, "storage.solaris.nicknames", NULL)) != NULL) { 338*18c2aff7Sartem for (j = 0; nicknames[j] != NULL; j++) { 339*18c2aff7Sartem (void) printf("%s%s", comma ? "," : "", 340*18c2aff7Sartem nicknames[j]); 341*18c2aff7Sartem comma = B_TRUE; 342*18c2aff7Sartem } 343*18c2aff7Sartem } 344*18c2aff7Sartem 345*18c2aff7Sartem if (((volume_label = libhal_device_get_property_string(hal_ctx, 346*18c2aff7Sartem udis[i], "volume.label", NULL)) != NULL) && 347*18c2aff7Sartem (strlen(volume_label) > 0)) { 348*18c2aff7Sartem (void) printf("%s%s", comma ? "," : "", volume_label); 349*18c2aff7Sartem comma = B_TRUE; 350*18c2aff7Sartem } 351*18c2aff7Sartem 352*18c2aff7Sartem if (((mount_point = libhal_device_get_property_string(hal_ctx, 353*18c2aff7Sartem udis[i], "volume.mount_point", NULL)) != NULL) && 354*18c2aff7Sartem (strlen(mount_point) > 0)) { 355*18c2aff7Sartem (void) printf("%s%s", comma ? "," : "", mount_point); 356*18c2aff7Sartem comma = B_TRUE; 357*18c2aff7Sartem } 358*18c2aff7Sartem 359*18c2aff7Sartem (void) printf("\n"); 360*18c2aff7Sartem 361*18c2aff7Sartem libhal_free_string_array(nicknames); 362*18c2aff7Sartem libhal_free_string(drive_udi); 363*18c2aff7Sartem libhal_free_string(volume_label); 364*18c2aff7Sartem libhal_free_string(mount_point); 365*18c2aff7Sartem libhal_free_string(block_device); 366*18c2aff7Sartem } 367*18c2aff7Sartem libhal_free_string_array(udis); 368*18c2aff7Sartem } 369*18c2aff7Sartem 370*18c2aff7Sartem 371*18c2aff7Sartem /* 372*18c2aff7Sartem * find volume by nickname 373*18c2aff7Sartem * returns the LibHalDrive object and a list of LibHalVolume objects. 374*18c2aff7Sartem */ 375*18c2aff7Sartem LibHalDrive * 376*18c2aff7Sartem rmm_hal_volume_findby_nickname(LibHalContext *hal_ctx, const char *name, 377*18c2aff7Sartem GSList **volumes) 378*18c2aff7Sartem { 379*18c2aff7Sartem DBusError error; 380*18c2aff7Sartem LibHalDrive *drive = NULL; 381*18c2aff7Sartem LibHalDrive *drive_tmp; 382*18c2aff7Sartem char **udis; 383*18c2aff7Sartem int num_udis; 384*18c2aff7Sartem char **nicknames; 385*18c2aff7Sartem int i, j; 386*18c2aff7Sartem 387*18c2aff7Sartem *volumes = NULL; 388*18c2aff7Sartem 389*18c2aff7Sartem dbus_error_init(&error); 390*18c2aff7Sartem 391*18c2aff7Sartem if ((udis = libhal_find_device_by_capability(hal_ctx, "storage", 392*18c2aff7Sartem &num_udis, &error)) == NULL) { 393*18c2aff7Sartem rmm_dbus_error_free(&error); 394*18c2aff7Sartem return (NULL); 395*18c2aff7Sartem } 396*18c2aff7Sartem 397*18c2aff7Sartem /* find a drive by nickname */ 398*18c2aff7Sartem for (i = 0; (i < num_udis) && (drive == NULL); i++) { 399*18c2aff7Sartem if ((nicknames = libhal_device_get_property_strlist(hal_ctx, 400*18c2aff7Sartem udis[i], "storage.solaris.nicknames", &error)) == NULL) { 401*18c2aff7Sartem rmm_dbus_error_free(&error); 402*18c2aff7Sartem continue; 403*18c2aff7Sartem } 404*18c2aff7Sartem for (j = 0; (nicknames[j] != NULL) && (drive == NULL); j++) { 405*18c2aff7Sartem if (strcmp(nicknames[j], name) == 0) { 406*18c2aff7Sartem drive = libhal_drive_from_udi(hal_ctx, udis[i]); 407*18c2aff7Sartem } 408*18c2aff7Sartem } 409*18c2aff7Sartem libhal_free_string_array(nicknames); 410*18c2aff7Sartem } 411*18c2aff7Sartem libhal_free_string_array(udis); 412*18c2aff7Sartem 413*18c2aff7Sartem if (drive != NULL) { 414*18c2aff7Sartem /* found the drive, now find its volumes */ 415*18c2aff7Sartem if ((drive_tmp = rmm_hal_volume_findby(hal_ctx, 416*18c2aff7Sartem "block.storage_device", libhal_drive_get_udi(drive), 417*18c2aff7Sartem volumes)) != NULL) { 418*18c2aff7Sartem libhal_drive_free(drive_tmp); 419*18c2aff7Sartem } 420*18c2aff7Sartem } 421*18c2aff7Sartem 422*18c2aff7Sartem rmm_dbus_error_free(&error); 423*18c2aff7Sartem 424*18c2aff7Sartem return (drive); 425*18c2aff7Sartem } 426*18c2aff7Sartem 427*18c2aff7Sartem void 428*18c2aff7Sartem rmm_volumes_free(GSList *volumes) 429*18c2aff7Sartem { 430*18c2aff7Sartem GSList *i; 431*18c2aff7Sartem 432*18c2aff7Sartem for (i = volumes; i != NULL; i = g_slist_next(i)) { 433*18c2aff7Sartem libhal_volume_free((LibHalVolume *)(i->data)); 434*18c2aff7Sartem } 435*18c2aff7Sartem g_slist_free(volumes); 436*18c2aff7Sartem } 437*18c2aff7Sartem 438*18c2aff7Sartem /* 439*18c2aff7Sartem * Call HAL's Mount() method on the given device 440*18c2aff7Sartem */ 441*18c2aff7Sartem boolean_t 442*18c2aff7Sartem rmm_hal_mount(LibHalContext *hal_ctx, const char *udi, 443*18c2aff7Sartem char **opts, int num_opts, char *mountpoint, DBusError *error) 444*18c2aff7Sartem { 445*18c2aff7Sartem DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx); 446*18c2aff7Sartem DBusMessage *dmesg, *reply; 447*18c2aff7Sartem char *fstype; 448*18c2aff7Sartem 449*18c2aff7Sartem dprintf("mounting %s...\n", udi); 450*18c2aff7Sartem 451*18c2aff7Sartem if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi, 452*18c2aff7Sartem "org.freedesktop.Hal.Device.Volume", "Mount"))) { 453*18c2aff7Sartem dprintf( 454*18c2aff7Sartem "mount failed for %s: cannot create dbus message\n", udi); 455*18c2aff7Sartem return (B_FALSE); 456*18c2aff7Sartem } 457*18c2aff7Sartem 458*18c2aff7Sartem fstype = ""; 459*18c2aff7Sartem if (mountpoint == NULL) { 460*18c2aff7Sartem mountpoint = ""; 461*18c2aff7Sartem } 462*18c2aff7Sartem 463*18c2aff7Sartem if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &mountpoint, 464*18c2aff7Sartem DBUS_TYPE_STRING, &fstype, 465*18c2aff7Sartem DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &opts, num_opts, 466*18c2aff7Sartem DBUS_TYPE_INVALID)) { 467*18c2aff7Sartem dprintf("mount failed for %s: cannot append args\n", udi); 468*18c2aff7Sartem dbus_message_unref(dmesg); 469*18c2aff7Sartem return (B_FALSE); 470*18c2aff7Sartem } 471*18c2aff7Sartem 472*18c2aff7Sartem dbus_error_init(error); 473*18c2aff7Sartem if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn, 474*18c2aff7Sartem dmesg, -1, error))) { 475*18c2aff7Sartem dprintf("mount failed for %s: %s\n", udi, error->message); 476*18c2aff7Sartem dbus_message_unref(dmesg); 477*18c2aff7Sartem return (B_FALSE); 478*18c2aff7Sartem } 479*18c2aff7Sartem 480*18c2aff7Sartem dprintf("mounted %s\n", udi); 481*18c2aff7Sartem 482*18c2aff7Sartem dbus_message_unref(dmesg); 483*18c2aff7Sartem dbus_message_unref(reply); 484*18c2aff7Sartem 485*18c2aff7Sartem rmm_dbus_error_free(error); 486*18c2aff7Sartem 487*18c2aff7Sartem return (B_TRUE); 488*18c2aff7Sartem } 489*18c2aff7Sartem 490*18c2aff7Sartem 491*18c2aff7Sartem /* 492*18c2aff7Sartem * Call HAL's Unmount() method on the given device 493*18c2aff7Sartem */ 494*18c2aff7Sartem boolean_t 495*18c2aff7Sartem rmm_hal_unmount(LibHalContext *hal_ctx, const char *udi, DBusError *error) 496*18c2aff7Sartem { 497*18c2aff7Sartem DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx); 498*18c2aff7Sartem DBusMessage *dmesg, *reply; 499*18c2aff7Sartem char **opts = NULL; 500*18c2aff7Sartem 501*18c2aff7Sartem dprintf("unmounting %s...\n", udi); 502*18c2aff7Sartem 503*18c2aff7Sartem if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi, 504*18c2aff7Sartem "org.freedesktop.Hal.Device.Volume", "Unmount"))) { 505*18c2aff7Sartem dprintf( 506*18c2aff7Sartem "unmount failed %s: cannot create dbus message\n", udi); 507*18c2aff7Sartem return (B_FALSE); 508*18c2aff7Sartem } 509*18c2aff7Sartem 510*18c2aff7Sartem if (!dbus_message_append_args(dmesg, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, 511*18c2aff7Sartem &opts, 0, DBUS_TYPE_INVALID)) { 512*18c2aff7Sartem dprintf("unmount failed %s: cannot append args\n", udi); 513*18c2aff7Sartem dbus_message_unref(dmesg); 514*18c2aff7Sartem return (B_FALSE); 515*18c2aff7Sartem } 516*18c2aff7Sartem 517*18c2aff7Sartem dbus_error_init(error); 518*18c2aff7Sartem if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn, 519*18c2aff7Sartem dmesg, -1, error))) { 520*18c2aff7Sartem dprintf("unmount failed for %s: %s\n", udi, error->message); 521*18c2aff7Sartem dbus_message_unref(dmesg); 522*18c2aff7Sartem return (B_FALSE); 523*18c2aff7Sartem } 524*18c2aff7Sartem 525*18c2aff7Sartem dprintf("unmounted %s\n", udi); 526*18c2aff7Sartem 527*18c2aff7Sartem dbus_message_unref(dmesg); 528*18c2aff7Sartem dbus_message_unref(reply); 529*18c2aff7Sartem 530*18c2aff7Sartem rmm_dbus_error_free(error); 531*18c2aff7Sartem 532*18c2aff7Sartem return (B_TRUE); 533*18c2aff7Sartem } 534*18c2aff7Sartem 535*18c2aff7Sartem 536*18c2aff7Sartem /* 537*18c2aff7Sartem * Call HAL's Eject() method on the given device 538*18c2aff7Sartem */ 539*18c2aff7Sartem boolean_t 540*18c2aff7Sartem rmm_hal_eject(LibHalContext *hal_ctx, const char *udi, DBusError *error) 541*18c2aff7Sartem { 542*18c2aff7Sartem DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx); 543*18c2aff7Sartem DBusMessage *dmesg, *reply; 544*18c2aff7Sartem char **options = NULL; 545*18c2aff7Sartem uint_t num_options = 0; 546*18c2aff7Sartem 547*18c2aff7Sartem dprintf("ejecting %s...\n", udi); 548*18c2aff7Sartem 549*18c2aff7Sartem if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi, 550*18c2aff7Sartem "org.freedesktop.Hal.Device.Storage", "Eject"))) { 551*18c2aff7Sartem dprintf("eject %s: cannot create dbus message\n", udi); 552*18c2aff7Sartem return (B_FALSE); 553*18c2aff7Sartem } 554*18c2aff7Sartem 555*18c2aff7Sartem if (!dbus_message_append_args(dmesg, 556*18c2aff7Sartem DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options, 557*18c2aff7Sartem DBUS_TYPE_INVALID)) { 558*18c2aff7Sartem dprintf("eject %s: cannot append args to dbus message ", udi); 559*18c2aff7Sartem dbus_message_unref(dmesg); 560*18c2aff7Sartem return (B_FALSE); 561*18c2aff7Sartem } 562*18c2aff7Sartem 563*18c2aff7Sartem dbus_error_init(error); 564*18c2aff7Sartem if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn, 565*18c2aff7Sartem dmesg, -1, error))) { 566*18c2aff7Sartem dprintf("eject %s: %s\n", udi, error->message); 567*18c2aff7Sartem dbus_message_unref(dmesg); 568*18c2aff7Sartem return (B_FALSE); 569*18c2aff7Sartem } 570*18c2aff7Sartem 571*18c2aff7Sartem dprintf("ejected %s\n", udi); 572*18c2aff7Sartem 573*18c2aff7Sartem dbus_message_unref(dmesg); 574*18c2aff7Sartem dbus_message_unref(reply); 575*18c2aff7Sartem 576*18c2aff7Sartem rmm_dbus_error_free(error); 577*18c2aff7Sartem 578*18c2aff7Sartem return (B_TRUE); 579*18c2aff7Sartem } 580*18c2aff7Sartem 581*18c2aff7Sartem /* 582*18c2aff7Sartem * Call HAL's CloseTray() method on the given device 583*18c2aff7Sartem */ 584*18c2aff7Sartem boolean_t 585*18c2aff7Sartem rmm_hal_closetray(LibHalContext *hal_ctx, const char *udi, DBusError *error) 586*18c2aff7Sartem { 587*18c2aff7Sartem DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx); 588*18c2aff7Sartem DBusMessage *dmesg, *reply; 589*18c2aff7Sartem char **options = NULL; 590*18c2aff7Sartem uint_t num_options = 0; 591*18c2aff7Sartem 592*18c2aff7Sartem dprintf("closing tray %s...\n", udi); 593*18c2aff7Sartem 594*18c2aff7Sartem if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi, 595*18c2aff7Sartem "org.freedesktop.Hal.Device.Storage", "CloseTray"))) { 596*18c2aff7Sartem dprintf( 597*18c2aff7Sartem "closetray failed for %s: cannot create dbus message\n", 598*18c2aff7Sartem udi); 599*18c2aff7Sartem return (B_FALSE); 600*18c2aff7Sartem } 601*18c2aff7Sartem 602*18c2aff7Sartem if (!dbus_message_append_args(dmesg, 603*18c2aff7Sartem DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options, 604*18c2aff7Sartem DBUS_TYPE_INVALID)) { 605*18c2aff7Sartem dprintf("closetray %s: cannot append args to dbus message ", 606*18c2aff7Sartem udi); 607*18c2aff7Sartem dbus_message_unref(dmesg); 608*18c2aff7Sartem return (B_FALSE); 609*18c2aff7Sartem } 610*18c2aff7Sartem 611*18c2aff7Sartem dbus_error_init(error); 612*18c2aff7Sartem if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn, 613*18c2aff7Sartem dmesg, -1, error))) { 614*18c2aff7Sartem dprintf("closetray failed for %s: %s\n", udi, error->message); 615*18c2aff7Sartem dbus_message_unref(dmesg); 616*18c2aff7Sartem return (B_FALSE); 617*18c2aff7Sartem } 618*18c2aff7Sartem 619*18c2aff7Sartem dprintf("closetray ok %s\n", udi); 620*18c2aff7Sartem 621*18c2aff7Sartem dbus_message_unref(dmesg); 622*18c2aff7Sartem dbus_message_unref(reply); 623*18c2aff7Sartem 624*18c2aff7Sartem rmm_dbus_error_free(error); 625*18c2aff7Sartem 626*18c2aff7Sartem return (B_TRUE); 627*18c2aff7Sartem } 628*18c2aff7Sartem 629*18c2aff7Sartem /* 630*18c2aff7Sartem * Call HAL's Rescan() method on the given device 631*18c2aff7Sartem */ 632*18c2aff7Sartem boolean_t 633*18c2aff7Sartem rmm_hal_rescan(LibHalContext *hal_ctx, const char *udi, DBusError *error) 634*18c2aff7Sartem { 635*18c2aff7Sartem DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx); 636*18c2aff7Sartem DBusMessage *dmesg, *reply; 637*18c2aff7Sartem 638*18c2aff7Sartem dprintf("rescanning %s...\n", udi); 639*18c2aff7Sartem 640*18c2aff7Sartem if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi, 641*18c2aff7Sartem "org.freedesktop.Hal.Device", "Rescan"))) { 642*18c2aff7Sartem dprintf("rescan failed for %s: cannot create dbus message\n", 643*18c2aff7Sartem udi); 644*18c2aff7Sartem return (B_FALSE); 645*18c2aff7Sartem } 646*18c2aff7Sartem 647*18c2aff7Sartem dbus_error_init(error); 648*18c2aff7Sartem if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn, 649*18c2aff7Sartem dmesg, -1, error))) { 650*18c2aff7Sartem dprintf("rescan failed for %s: %s\n", udi, error->message); 651*18c2aff7Sartem dbus_message_unref(dmesg); 652*18c2aff7Sartem return (B_FALSE); 653*18c2aff7Sartem } 654*18c2aff7Sartem 655*18c2aff7Sartem dprintf("rescan ok %s\n", udi); 656*18c2aff7Sartem 657*18c2aff7Sartem dbus_message_unref(dmesg); 658*18c2aff7Sartem dbus_message_unref(reply); 659*18c2aff7Sartem 660*18c2aff7Sartem rmm_dbus_error_free(error); 661*18c2aff7Sartem 662*18c2aff7Sartem return (B_TRUE); 663*18c2aff7Sartem } 664*18c2aff7Sartem 665*18c2aff7Sartem boolean_t 666*18c2aff7Sartem rmm_hal_claim_branch(LibHalContext *hal_ctx, const char *udi) 667*18c2aff7Sartem { 668*18c2aff7Sartem DBusError error; 669*18c2aff7Sartem DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx); 670*18c2aff7Sartem DBusMessage *dmesg, *reply; 671*18c2aff7Sartem const char *claimed_by = "rmvolmgr"; 672*18c2aff7Sartem 673*18c2aff7Sartem dprintf("claiming branch %s...\n", udi); 674*18c2aff7Sartem 675*18c2aff7Sartem if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", 676*18c2aff7Sartem "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager", 677*18c2aff7Sartem "ClaimBranch"))) { 678*18c2aff7Sartem dprintf("cannot create dbus message\n"); 679*18c2aff7Sartem return (B_FALSE); 680*18c2aff7Sartem } 681*18c2aff7Sartem 682*18c2aff7Sartem if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &udi, 683*18c2aff7Sartem DBUS_TYPE_STRING, &claimed_by, DBUS_TYPE_INVALID)) { 684*18c2aff7Sartem dprintf("cannot append args to dbus message\n"); 685*18c2aff7Sartem dbus_message_unref(dmesg); 686*18c2aff7Sartem return (B_FALSE); 687*18c2aff7Sartem } 688*18c2aff7Sartem 689*18c2aff7Sartem dbus_error_init(&error); 690*18c2aff7Sartem if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn, 691*18c2aff7Sartem dmesg, -1, &error))) { 692*18c2aff7Sartem dprintf("cannot send dbus message\n"); 693*18c2aff7Sartem dbus_message_unref(dmesg); 694*18c2aff7Sartem rmm_dbus_error_free(&error); 695*18c2aff7Sartem return (B_FALSE); 696*18c2aff7Sartem } 697*18c2aff7Sartem 698*18c2aff7Sartem dprintf("claim branch ok %s\n", udi); 699*18c2aff7Sartem 700*18c2aff7Sartem dbus_message_unref(dmesg); 701*18c2aff7Sartem dbus_message_unref(reply); 702*18c2aff7Sartem 703*18c2aff7Sartem return (B_TRUE); 704*18c2aff7Sartem } 705*18c2aff7Sartem 706*18c2aff7Sartem boolean_t 707*18c2aff7Sartem rmm_hal_unclaim_branch(LibHalContext *hal_ctx, const char *udi) 708*18c2aff7Sartem { 709*18c2aff7Sartem DBusError error; 710*18c2aff7Sartem DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx); 711*18c2aff7Sartem DBusMessage *dmesg, *reply; 712*18c2aff7Sartem const char *claimed_by = "rmvolmgr"; 713*18c2aff7Sartem 714*18c2aff7Sartem dprintf("unclaiming branch %s...\n", udi); 715*18c2aff7Sartem 716*18c2aff7Sartem if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", 717*18c2aff7Sartem "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager", 718*18c2aff7Sartem "UnclaimBranch"))) { 719*18c2aff7Sartem dprintf("cannot create dbus message\n"); 720*18c2aff7Sartem return (B_FALSE); 721*18c2aff7Sartem } 722*18c2aff7Sartem 723*18c2aff7Sartem if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &udi, 724*18c2aff7Sartem DBUS_TYPE_STRING, &claimed_by, DBUS_TYPE_INVALID)) { 725*18c2aff7Sartem dprintf("cannot append args to dbus message\n"); 726*18c2aff7Sartem dbus_message_unref(dmesg); 727*18c2aff7Sartem return (B_FALSE); 728*18c2aff7Sartem } 729*18c2aff7Sartem 730*18c2aff7Sartem dbus_error_init(&error); 731*18c2aff7Sartem if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn, 732*18c2aff7Sartem dmesg, -1, &error))) { 733*18c2aff7Sartem dprintf("cannot send dbus message\n"); 734*18c2aff7Sartem dbus_message_unref(dmesg); 735*18c2aff7Sartem rmm_dbus_error_free(&error); 736*18c2aff7Sartem return (B_FALSE); 737*18c2aff7Sartem } 738*18c2aff7Sartem 739*18c2aff7Sartem dprintf("unclaim branch ok %s\n", udi); 740*18c2aff7Sartem 741*18c2aff7Sartem dbus_message_unref(dmesg); 742*18c2aff7Sartem dbus_message_unref(reply); 743*18c2aff7Sartem 744*18c2aff7Sartem return (B_TRUE); 745*18c2aff7Sartem } 746*18c2aff7Sartem 747*18c2aff7Sartem static boolean_t 748*18c2aff7Sartem rmm_action_one(LibHalContext *hal_ctx, const char *name, action_t action, 749*18c2aff7Sartem const char *dev, const char *udi, LibHalVolume *v, 750*18c2aff7Sartem char **opts, int num_opts, char *mountpoint) 751*18c2aff7Sartem { 752*18c2aff7Sartem char dev_str[MAXPATHLEN]; 753*18c2aff7Sartem char *mountp; 754*18c2aff7Sartem DBusError error; 755*18c2aff7Sartem boolean_t ret = B_FALSE; 756*18c2aff7Sartem 757*18c2aff7Sartem if (strcmp(name, dev) == 0) { 758*18c2aff7Sartem (void) snprintf(dev_str, sizeof (dev_str), name); 759*18c2aff7Sartem } else { 760*18c2aff7Sartem (void) snprintf(dev_str, sizeof (dev_str), "%s %s", name, dev); 761*18c2aff7Sartem } 762*18c2aff7Sartem 763*18c2aff7Sartem dbus_error_init(&error); 764*18c2aff7Sartem 765*18c2aff7Sartem switch (action) { 766*18c2aff7Sartem case EJECT: 767*18c2aff7Sartem ret = rmm_hal_eject(hal_ctx, udi, &error); 768*18c2aff7Sartem break; 769*18c2aff7Sartem case INSERT: 770*18c2aff7Sartem case REMOUNT: 771*18c2aff7Sartem if (libhal_volume_is_mounted(v)) { 772*18c2aff7Sartem goto done; 773*18c2aff7Sartem } 774*18c2aff7Sartem ret = rmm_hal_mount(hal_ctx, udi, 775*18c2aff7Sartem opts, num_opts, mountpoint, &error); 776*18c2aff7Sartem break; 777*18c2aff7Sartem case UNMOUNT: 778*18c2aff7Sartem if (!libhal_volume_is_mounted(v)) { 779*18c2aff7Sartem goto done; 780*18c2aff7Sartem } 781*18c2aff7Sartem ret = rmm_hal_unmount(hal_ctx, udi, &error); 782*18c2aff7Sartem break; 783*18c2aff7Sartem case CLOSETRAY: 784*18c2aff7Sartem ret = rmm_hal_closetray(hal_ctx, udi, &error); 785*18c2aff7Sartem break; 786*18c2aff7Sartem } 787*18c2aff7Sartem 788*18c2aff7Sartem if (!ret) { 789*18c2aff7Sartem (void) fprintf(stderr, gettext("%s of %s failed: %s\n"), 790*18c2aff7Sartem action_strings[action], dev_str, rmm_strerror(&error, -1)); 791*18c2aff7Sartem goto done; 792*18c2aff7Sartem } 793*18c2aff7Sartem 794*18c2aff7Sartem switch (action) { 795*18c2aff7Sartem case EJECT: 796*18c2aff7Sartem (void) printf(gettext("%s ejected\n"), dev_str); 797*18c2aff7Sartem break; 798*18c2aff7Sartem case INSERT: 799*18c2aff7Sartem case REMOUNT: 800*18c2aff7Sartem mountp = rmm_get_mnttab_mount_point(dev); 801*18c2aff7Sartem if (mountp != NULL) { 802*18c2aff7Sartem (void) printf(gettext("%s mounted at %s\n"), 803*18c2aff7Sartem dev_str, mountp); 804*18c2aff7Sartem free(mountp); 805*18c2aff7Sartem } 806*18c2aff7Sartem break; 807*18c2aff7Sartem case UNMOUNT: 808*18c2aff7Sartem (void) printf(gettext("%s unmounted\n"), dev_str); 809*18c2aff7Sartem break; 810*18c2aff7Sartem case CLOSETRAY: 811*18c2aff7Sartem (void) printf(gettext("%s tray closed\n"), dev_str); 812*18c2aff7Sartem break; 813*18c2aff7Sartem } 814*18c2aff7Sartem 815*18c2aff7Sartem done: 816*18c2aff7Sartem rmm_dbus_error_free(&error); 817*18c2aff7Sartem return (ret); 818*18c2aff7Sartem } 819*18c2aff7Sartem 820*18c2aff7Sartem /* 821*18c2aff7Sartem * top level action routine 822*18c2aff7Sartem * 823*18c2aff7Sartem * If non-null 'aa' is passed, it will be used, otherwise a local copy 824*18c2aff7Sartem * will be created. 825*18c2aff7Sartem */ 826*18c2aff7Sartem boolean_t 827*18c2aff7Sartem rmm_action(LibHalContext *hal_ctx, const char *name, action_t action, 828*18c2aff7Sartem struct action_arg *aap, char **opts, int num_opts, char *mountpoint) 829*18c2aff7Sartem { 830*18c2aff7Sartem DBusError error; 831*18c2aff7Sartem GSList *volumes, *i; 832*18c2aff7Sartem LibHalDrive *d; 833*18c2aff7Sartem LibHalVolume *v; 834*18c2aff7Sartem const char *udi, *d_udi; 835*18c2aff7Sartem const char *dev, *d_dev; 836*18c2aff7Sartem struct action_arg aa_local; 837*18c2aff7Sartem boolean_t ret = B_FALSE; 838*18c2aff7Sartem 839*18c2aff7Sartem dprintf("rmm_action %s %s\n", name, action_strings[action]); 840*18c2aff7Sartem 841*18c2aff7Sartem if (aap == NULL) { 842*18c2aff7Sartem aap = &aa_local; 843*18c2aff7Sartem } 844*18c2aff7Sartem 845*18c2aff7Sartem dbus_error_init(&error); 846*18c2aff7Sartem 847*18c2aff7Sartem /* find the drive and its volumes */ 848*18c2aff7Sartem d = rmm_hal_volume_find(hal_ctx, name, &error, &volumes); 849*18c2aff7Sartem rmm_dbus_error_free(&error); 850*18c2aff7Sartem if (d == NULL) { 851*18c2aff7Sartem (void) fprintf(stderr, gettext("cannot find '%s'\n"), name); 852*18c2aff7Sartem return (B_FALSE); 853*18c2aff7Sartem } 854*18c2aff7Sartem d_udi = libhal_drive_get_udi(d); 855*18c2aff7Sartem d_dev = libhal_drive_get_device_file(d); 856*18c2aff7Sartem if ((d_udi == NULL) || (d_dev == NULL)) { 857*18c2aff7Sartem goto out; 858*18c2aff7Sartem } 859*18c2aff7Sartem 860*18c2aff7Sartem /* 861*18c2aff7Sartem * For those drives that do not require media eject, 862*18c2aff7Sartem * EJECT turns into UNMOUNT. 863*18c2aff7Sartem */ 864*18c2aff7Sartem if ((action == EJECT) && !libhal_drive_requires_eject(d)) { 865*18c2aff7Sartem action = UNMOUNT; 866*18c2aff7Sartem } 867*18c2aff7Sartem 868*18c2aff7Sartem /* per drive action */ 869*18c2aff7Sartem if ((action == EJECT) || (action == CLOSETRAY)) { 870*18c2aff7Sartem ret = rmm_action_one(hal_ctx, name, action, d_dev, d_udi, NULL, 871*18c2aff7Sartem opts, num_opts, NULL); 872*18c2aff7Sartem 873*18c2aff7Sartem if (!ret || (action == CLOSETRAY)) { 874*18c2aff7Sartem goto out; 875*18c2aff7Sartem } 876*18c2aff7Sartem } 877*18c2aff7Sartem 878*18c2aff7Sartem /* per volume action */ 879*18c2aff7Sartem for (i = volumes; i != NULL; i = g_slist_next(i)) { 880*18c2aff7Sartem v = (LibHalVolume *)i->data; 881*18c2aff7Sartem udi = libhal_volume_get_udi(v); 882*18c2aff7Sartem dev = libhal_volume_get_device_file(v); 883*18c2aff7Sartem 884*18c2aff7Sartem if ((udi == NULL) || (dev == NULL)) { 885*18c2aff7Sartem continue; 886*18c2aff7Sartem } 887*18c2aff7Sartem if (aap == &aa_local) { 888*18c2aff7Sartem if (!rmm_volume_aa_from_prop(hal_ctx, udi, v, aap)) { 889*18c2aff7Sartem dprintf("rmm_volume_aa_from_prop failed %s\n", 890*18c2aff7Sartem udi); 891*18c2aff7Sartem continue; 892*18c2aff7Sartem } 893*18c2aff7Sartem } 894*18c2aff7Sartem aap->aa_action = action; 895*18c2aff7Sartem 896*18c2aff7Sartem /* ejected above, just need postprocess */ 897*18c2aff7Sartem if (action != EJECT) { 898*18c2aff7Sartem ret = rmm_action_one(hal_ctx, name, action, dev, udi, v, 899*18c2aff7Sartem opts, num_opts, mountpoint); 900*18c2aff7Sartem } 901*18c2aff7Sartem if (ret) { 902*18c2aff7Sartem (void) vold_postprocess(hal_ctx, udi, aap); 903*18c2aff7Sartem } 904*18c2aff7Sartem 905*18c2aff7Sartem libhal_volume_free(v); 906*18c2aff7Sartem if (aap == &aa_local) { 907*18c2aff7Sartem rmm_volume_aa_free(aap); 908*18c2aff7Sartem } 909*18c2aff7Sartem } 910*18c2aff7Sartem 911*18c2aff7Sartem out: 912*18c2aff7Sartem g_slist_free(volumes); 913*18c2aff7Sartem libhal_drive_free(d); 914*18c2aff7Sartem 915*18c2aff7Sartem return (ret); 916*18c2aff7Sartem } 917*18c2aff7Sartem 918*18c2aff7Sartem 919*18c2aff7Sartem /* 920*18c2aff7Sartem * rescan by name 921*18c2aff7Sartem * if name is NULL, rescan all drives 922*18c2aff7Sartem */ 923*18c2aff7Sartem boolean_t 924*18c2aff7Sartem rmm_rescan(LibHalContext *hal_ctx, const char *name, boolean_t query) 925*18c2aff7Sartem { 926*18c2aff7Sartem DBusError error; 927*18c2aff7Sartem GSList *volumes; 928*18c2aff7Sartem LibHalDrive *drive = NULL; 929*18c2aff7Sartem const char *drive_udi; 930*18c2aff7Sartem char **udis; 931*18c2aff7Sartem int num_udis; 932*18c2aff7Sartem char *nickname; 933*18c2aff7Sartem char **nicks = NULL; 934*18c2aff7Sartem boolean_t do_free_udis = FALSE; 935*18c2aff7Sartem int i; 936*18c2aff7Sartem int ret = 0; 937*18c2aff7Sartem 938*18c2aff7Sartem dprintf("rmm_rescan %s\n", name != NULL ? name : "all"); 939*18c2aff7Sartem 940*18c2aff7Sartem dbus_error_init(&error); 941*18c2aff7Sartem 942*18c2aff7Sartem if (name != NULL) { 943*18c2aff7Sartem if ((drive = rmm_hal_volume_find(hal_ctx, name, &error, 944*18c2aff7Sartem &volumes)) == NULL) { 945*18c2aff7Sartem rmm_dbus_error_free(&error); 946*18c2aff7Sartem (void) fprintf(stderr, 947*18c2aff7Sartem gettext("cannot find '%s'\n"), name); 948*18c2aff7Sartem return (B_FALSE); 949*18c2aff7Sartem } 950*18c2aff7Sartem rmm_dbus_error_free(&error); 951*18c2aff7Sartem g_slist_free(volumes); 952*18c2aff7Sartem 953*18c2aff7Sartem drive_udi = libhal_drive_get_udi(drive); 954*18c2aff7Sartem udis = (char **)&drive_udi; 955*18c2aff7Sartem num_udis = 1; 956*18c2aff7Sartem } else { 957*18c2aff7Sartem if ((udis = libhal_find_device_by_capability(hal_ctx, 958*18c2aff7Sartem "storage", &num_udis, &error)) == NULL) { 959*18c2aff7Sartem rmm_dbus_error_free(&error); 960*18c2aff7Sartem return (B_TRUE); 961*18c2aff7Sartem } 962*18c2aff7Sartem rmm_dbus_error_free(&error); 963*18c2aff7Sartem do_free_udis = TRUE; 964*18c2aff7Sartem } 965*18c2aff7Sartem 966*18c2aff7Sartem for (i = 0; i < num_udis; i++) { 967*18c2aff7Sartem if (name == NULL) { 968*18c2aff7Sartem nicks = libhal_device_get_property_strlist(hal_ctx, 969*18c2aff7Sartem udis[i], "storage.solaris.nicknames", NULL); 970*18c2aff7Sartem if (nicks != NULL) { 971*18c2aff7Sartem nickname = nicks[0]; 972*18c2aff7Sartem } else { 973*18c2aff7Sartem nickname = ""; 974*18c2aff7Sartem } 975*18c2aff7Sartem } 976*18c2aff7Sartem if (!(ret = rmm_hal_rescan(hal_ctx, udis[i], &error))) { 977*18c2aff7Sartem (void) fprintf(stderr, 978*18c2aff7Sartem gettext("rescan of %s failed: %s\n"), 979*18c2aff7Sartem name ? name : nickname, 980*18c2aff7Sartem rmm_strerror(&error, -1)); 981*18c2aff7Sartem libhal_free_string_array(nicks); 982*18c2aff7Sartem continue; 983*18c2aff7Sartem } 984*18c2aff7Sartem if (query) { 985*18c2aff7Sartem printf(gettext("%s is%s available\n"), 986*18c2aff7Sartem name ? name : nickname, 987*18c2aff7Sartem libhal_device_get_property_bool(hal_ctx, udis[i], 988*18c2aff7Sartem "storage.removable.media_available", NULL) ? 989*18c2aff7Sartem "" : " not"); 990*18c2aff7Sartem } 991*18c2aff7Sartem libhal_free_string_array(nicks); 992*18c2aff7Sartem } 993*18c2aff7Sartem 994*18c2aff7Sartem if (drive != NULL) { 995*18c2aff7Sartem libhal_drive_free(drive); 996*18c2aff7Sartem } 997*18c2aff7Sartem if (do_free_udis) { 998*18c2aff7Sartem libhal_free_string_array(udis); 999*18c2aff7Sartem } 1000*18c2aff7Sartem 1001*18c2aff7Sartem return (ret); 1002*18c2aff7Sartem } 1003*18c2aff7Sartem 1004*18c2aff7Sartem 1005*18c2aff7Sartem /* 1006*18c2aff7Sartem * set action_arg from volume properties 1007*18c2aff7Sartem */ 1008*18c2aff7Sartem boolean_t 1009*18c2aff7Sartem rmm_volume_aa_from_prop(LibHalContext *hal_ctx, const char *udi_arg, 1010*18c2aff7Sartem LibHalVolume *volume_arg, struct action_arg *aap) 1011*18c2aff7Sartem { 1012*18c2aff7Sartem LibHalVolume *volume = volume_arg; 1013*18c2aff7Sartem const char *udi = udi_arg; 1014*18c2aff7Sartem const char *drive_udi; 1015*18c2aff7Sartem char *volume_label; 1016*18c2aff7Sartem char *mountpoint; 1017*18c2aff7Sartem int len; 1018*18c2aff7Sartem int ret = B_FALSE; 1019*18c2aff7Sartem 1020*18c2aff7Sartem /* at least udi or volume must be supplied */ 1021*18c2aff7Sartem if ((udi == NULL) && (volume == NULL)) { 1022*18c2aff7Sartem return (B_FALSE); 1023*18c2aff7Sartem } 1024*18c2aff7Sartem if (volume == NULL) { 1025*18c2aff7Sartem if ((volume = libhal_volume_from_udi(hal_ctx, udi)) == NULL) { 1026*18c2aff7Sartem dprintf("cannot get volume %s\n", udi); 1027*18c2aff7Sartem goto out; 1028*18c2aff7Sartem } 1029*18c2aff7Sartem } 1030*18c2aff7Sartem if (udi == NULL) { 1031*18c2aff7Sartem if ((udi = libhal_volume_get_udi(volume)) == NULL) { 1032*18c2aff7Sartem dprintf("cannot get udi\n"); 1033*18c2aff7Sartem goto out; 1034*18c2aff7Sartem } 1035*18c2aff7Sartem } 1036*18c2aff7Sartem drive_udi = libhal_volume_get_storage_device_udi(volume); 1037*18c2aff7Sartem 1038*18c2aff7Sartem if (!(aap->aa_symdev = libhal_device_get_property_string(hal_ctx, 1039*18c2aff7Sartem drive_udi, "storage.solaris.legacy.symdev", NULL))) { 1040*18c2aff7Sartem dprintf("property %s not found %s\n", 1041*18c2aff7Sartem "storage.solaris.legacy.symdev", drive_udi); 1042*18c2aff7Sartem goto out; 1043*18c2aff7Sartem } 1044*18c2aff7Sartem if (!(aap->aa_media = libhal_device_get_property_string(hal_ctx, 1045*18c2aff7Sartem drive_udi, "storage.solaris.legacy.media_type", NULL))) { 1046*18c2aff7Sartem dprintf("property %s not found %s\n", 1047*18c2aff7Sartem "storage.solaris.legacy.media_type", drive_udi); 1048*18c2aff7Sartem goto out; 1049*18c2aff7Sartem } 1050*18c2aff7Sartem 1051*18c2aff7Sartem /* name is derived from volume label */ 1052*18c2aff7Sartem aap->aa_name = NULL; 1053*18c2aff7Sartem if ((volume_label = (char *)libhal_device_get_property_string(hal_ctx, 1054*18c2aff7Sartem udi, "volume.label", NULL)) != NULL) { 1055*18c2aff7Sartem if ((len = strlen(volume_label)) > 0) { 1056*18c2aff7Sartem aap->aa_name = rmm_vold_convert_volume_label( 1057*18c2aff7Sartem volume_label, len); 1058*18c2aff7Sartem if (strlen(aap->aa_name) == 0) { 1059*18c2aff7Sartem free(aap->aa_name); 1060*18c2aff7Sartem aap->aa_name = NULL; 1061*18c2aff7Sartem } 1062*18c2aff7Sartem } 1063*18c2aff7Sartem libhal_free_string(volume_label); 1064*18c2aff7Sartem } 1065*18c2aff7Sartem /* if no label, then unnamed_<mediatype> */ 1066*18c2aff7Sartem if (aap->aa_name == NULL) { 1067*18c2aff7Sartem aap->aa_name = (char *)calloc(1, sizeof ("unnamed_floppyNNNN")); 1068*18c2aff7Sartem if (aap->aa_name == NULL) { 1069*18c2aff7Sartem goto out; 1070*18c2aff7Sartem } 1071*18c2aff7Sartem (void) snprintf(aap->aa_name, sizeof ("unnamed_floppyNNNN"), 1072*18c2aff7Sartem "unnamed_%s", aap->aa_media); 1073*18c2aff7Sartem } 1074*18c2aff7Sartem 1075*18c2aff7Sartem if (!(aap->aa_path = libhal_device_get_property_string(hal_ctx, udi, 1076*18c2aff7Sartem "block.device", NULL))) { 1077*18c2aff7Sartem dprintf("property %s not found %s\n", "block.device", udi); 1078*18c2aff7Sartem goto out; 1079*18c2aff7Sartem } 1080*18c2aff7Sartem if (!(aap->aa_rawpath = libhal_device_get_property_string(hal_ctx, udi, 1081*18c2aff7Sartem "block.solaris.raw_device", NULL))) { 1082*18c2aff7Sartem dprintf("property %s not found %s\n", 1083*18c2aff7Sartem "block.solaris.raw_device", udi); 1084*18c2aff7Sartem goto out; 1085*18c2aff7Sartem } 1086*18c2aff7Sartem if (!(aap->aa_type = libhal_device_get_property_string(hal_ctx, udi, 1087*18c2aff7Sartem "volume.fstype", NULL))) { 1088*18c2aff7Sartem dprintf("property %s not found %s\n", "volume.fstype", udi); 1089*18c2aff7Sartem goto out; 1090*18c2aff7Sartem } 1091*18c2aff7Sartem if (!libhal_device_get_property_bool(hal_ctx, udi, 1092*18c2aff7Sartem "volume.is_partition", NULL)) { 1093*18c2aff7Sartem aap->aa_partname = NULL; 1094*18c2aff7Sartem } else if (!(aap->aa_partname = libhal_device_get_property_string( 1095*18c2aff7Sartem hal_ctx, udi, "block.solaris.slice", NULL))) { 1096*18c2aff7Sartem dprintf("property %s not found %s\n", 1097*18c2aff7Sartem "block.solaris.slice", udi); 1098*18c2aff7Sartem goto out; 1099*18c2aff7Sartem } 1100*18c2aff7Sartem if (!(mountpoint = libhal_device_get_property_string(hal_ctx, udi, 1101*18c2aff7Sartem "volume.mount_point", NULL))) { 1102*18c2aff7Sartem dprintf("property %s not found %s\n", 1103*18c2aff7Sartem "volume.mount_point", udi); 1104*18c2aff7Sartem goto out; 1105*18c2aff7Sartem } 1106*18c2aff7Sartem /* 1107*18c2aff7Sartem * aa_mountpoint can be reallocated in rmm_volume_aa_update_mountpoint() 1108*18c2aff7Sartem * won't have to choose between free() or libhal_free_string() later on 1109*18c2aff7Sartem */ 1110*18c2aff7Sartem aap->aa_mountpoint = strdup(mountpoint); 1111*18c2aff7Sartem libhal_free_string(mountpoint); 1112*18c2aff7Sartem if (aap->aa_mountpoint == NULL) { 1113*18c2aff7Sartem dprintf("mountpoint is NULL %s\n", udi); 1114*18c2aff7Sartem goto out; 1115*18c2aff7Sartem } 1116*18c2aff7Sartem 1117*18c2aff7Sartem ret = B_TRUE; 1118*18c2aff7Sartem 1119*18c2aff7Sartem out: 1120*18c2aff7Sartem if ((volume != NULL) && (volume != volume_arg)) { 1121*18c2aff7Sartem libhal_volume_free(volume); 1122*18c2aff7Sartem } 1123*18c2aff7Sartem if (!ret) { 1124*18c2aff7Sartem rmm_volume_aa_free(aap); 1125*18c2aff7Sartem } 1126*18c2aff7Sartem return (ret); 1127*18c2aff7Sartem } 1128*18c2aff7Sartem 1129*18c2aff7Sartem /* ARGSUSED */ 1130*18c2aff7Sartem void 1131*18c2aff7Sartem rmm_volume_aa_update_mountpoint(LibHalContext *hal_ctx, const char *udi, 1132*18c2aff7Sartem struct action_arg *aap) 1133*18c2aff7Sartem { 1134*18c2aff7Sartem if (aap->aa_mountpoint != NULL) { 1135*18c2aff7Sartem free(aap->aa_mountpoint); 1136*18c2aff7Sartem } 1137*18c2aff7Sartem aap->aa_mountpoint = rmm_get_mnttab_mount_point(aap->aa_path); 1138*18c2aff7Sartem } 1139*18c2aff7Sartem 1140*18c2aff7Sartem void 1141*18c2aff7Sartem rmm_volume_aa_free(struct action_arg *aap) 1142*18c2aff7Sartem { 1143*18c2aff7Sartem if (aap->aa_symdev != NULL) { 1144*18c2aff7Sartem libhal_free_string(aap->aa_symdev); 1145*18c2aff7Sartem aap->aa_symdev = NULL; 1146*18c2aff7Sartem } 1147*18c2aff7Sartem if (aap->aa_name != NULL) { 1148*18c2aff7Sartem free(aap->aa_name); 1149*18c2aff7Sartem aap->aa_name = NULL; 1150*18c2aff7Sartem } 1151*18c2aff7Sartem if (aap->aa_path != NULL) { 1152*18c2aff7Sartem libhal_free_string(aap->aa_path); 1153*18c2aff7Sartem aap->aa_path = NULL; 1154*18c2aff7Sartem } 1155*18c2aff7Sartem if (aap->aa_rawpath != NULL) { 1156*18c2aff7Sartem libhal_free_string(aap->aa_rawpath); 1157*18c2aff7Sartem aap->aa_rawpath = NULL; 1158*18c2aff7Sartem } 1159*18c2aff7Sartem if (aap->aa_type != NULL) { 1160*18c2aff7Sartem libhal_free_string(aap->aa_type); 1161*18c2aff7Sartem aap->aa_type = NULL; 1162*18c2aff7Sartem } 1163*18c2aff7Sartem if (aap->aa_media != NULL) { 1164*18c2aff7Sartem libhal_free_string(aap->aa_media); 1165*18c2aff7Sartem aap->aa_media = NULL; 1166*18c2aff7Sartem } 1167*18c2aff7Sartem if (aap->aa_partname != NULL) { 1168*18c2aff7Sartem libhal_free_string(aap->aa_partname); 1169*18c2aff7Sartem aap->aa_partname = NULL; 1170*18c2aff7Sartem } 1171*18c2aff7Sartem if (aap->aa_mountpoint != NULL) { 1172*18c2aff7Sartem free(aap->aa_mountpoint); 1173*18c2aff7Sartem aap->aa_mountpoint = NULL; 1174*18c2aff7Sartem } 1175*18c2aff7Sartem } 1176*18c2aff7Sartem 1177*18c2aff7Sartem /* 1178*18c2aff7Sartem * get device's mount point from mnttab 1179*18c2aff7Sartem */ 1180*18c2aff7Sartem char * 1181*18c2aff7Sartem rmm_get_mnttab_mount_point(const char *special) 1182*18c2aff7Sartem { 1183*18c2aff7Sartem char *mount_point = NULL; 1184*18c2aff7Sartem FILE *f; 1185*18c2aff7Sartem struct mnttab mnt; 1186*18c2aff7Sartem struct mnttab mpref = { NULL, NULL, NULL, NULL, NULL }; 1187*18c2aff7Sartem 1188*18c2aff7Sartem if ((f = fopen(MNTTAB, "r")) != NULL) { 1189*18c2aff7Sartem mpref.mnt_special = (char *)special; 1190*18c2aff7Sartem if (getmntany(f, &mnt, &mpref) == 0) { 1191*18c2aff7Sartem mount_point = strdup(mnt.mnt_mountp); 1192*18c2aff7Sartem } 1193*18c2aff7Sartem fclose(f); 1194*18c2aff7Sartem } 1195*18c2aff7Sartem 1196*18c2aff7Sartem return (mount_point); 1197*18c2aff7Sartem } 1198*18c2aff7Sartem 1199*18c2aff7Sartem 1200*18c2aff7Sartem /* 1201*18c2aff7Sartem * get human readable string from error values 1202*18c2aff7Sartem */ 1203*18c2aff7Sartem const char * 1204*18c2aff7Sartem rmm_strerror(DBusError *dbus_error, int rmm_error) 1205*18c2aff7Sartem { 1206*18c2aff7Sartem const char *str; 1207*18c2aff7Sartem 1208*18c2aff7Sartem if ((dbus_error != NULL) && dbus_error_is_set(dbus_error)) { 1209*18c2aff7Sartem str = dbus_error->message; 1210*18c2aff7Sartem } else { 1211*18c2aff7Sartem switch (rmm_error) { 1212*18c2aff7Sartem case RMM_EOK: 1213*18c2aff7Sartem str = gettext("success"); 1214*18c2aff7Sartem break; 1215*18c2aff7Sartem case RMM_EDBUS_CONNECT: 1216*18c2aff7Sartem str = gettext("cannot connect to D-Bus"); 1217*18c2aff7Sartem break; 1218*18c2aff7Sartem case RMM_EHAL_CONNECT: 1219*18c2aff7Sartem str = gettext("cannot connect to HAL"); 1220*18c2aff7Sartem break; 1221*18c2aff7Sartem default: 1222*18c2aff7Sartem str = gettext("undefined error"); 1223*18c2aff7Sartem break; 1224*18c2aff7Sartem } 1225*18c2aff7Sartem } 1226*18c2aff7Sartem 1227*18c2aff7Sartem return (str); 1228*18c2aff7Sartem } 1229*18c2aff7Sartem 1230*18c2aff7Sartem void 1231*18c2aff7Sartem rmm_dbus_error_free(DBusError *error) 1232*18c2aff7Sartem { 1233*18c2aff7Sartem if (error != NULL && dbus_error_is_set(error)) { 1234*18c2aff7Sartem dbus_error_free(error); 1235*18c2aff7Sartem } 1236*18c2aff7Sartem } 1237*18c2aff7Sartem 1238*18c2aff7Sartem static int 1239*18c2aff7Sartem rmm_vold_isbadchar(int c) 1240*18c2aff7Sartem { 1241*18c2aff7Sartem int ret_val = 0; 1242*18c2aff7Sartem 1243*18c2aff7Sartem 1244*18c2aff7Sartem switch (c) { 1245*18c2aff7Sartem case '/': 1246*18c2aff7Sartem case ';': 1247*18c2aff7Sartem case '|': 1248*18c2aff7Sartem ret_val = 1; 1249*18c2aff7Sartem break; 1250*18c2aff7Sartem default: 1251*18c2aff7Sartem if (iscntrl(c) || isspace(c)) { 1252*18c2aff7Sartem ret_val = 1; 1253*18c2aff7Sartem } 1254*18c2aff7Sartem } 1255*18c2aff7Sartem 1256*18c2aff7Sartem return (ret_val); 1257*18c2aff7Sartem } 1258*18c2aff7Sartem 1259*18c2aff7Sartem char * 1260*18c2aff7Sartem rmm_vold_convert_volume_label(const char *name, size_t len) 1261*18c2aff7Sartem { 1262*18c2aff7Sartem char buf[MAXNAMELEN+1]; 1263*18c2aff7Sartem char *s = buf; 1264*18c2aff7Sartem int i; 1265*18c2aff7Sartem 1266*18c2aff7Sartem if (len > MAXNAMELEN) { 1267*18c2aff7Sartem len = MAXNAMELEN; 1268*18c2aff7Sartem } 1269*18c2aff7Sartem 1270*18c2aff7Sartem for (i = 0; i < len; i++) { 1271*18c2aff7Sartem if (name[i] == '\0') { 1272*18c2aff7Sartem break; 1273*18c2aff7Sartem } 1274*18c2aff7Sartem if (isgraph((int)name[i])) { 1275*18c2aff7Sartem if (isupper((int)name[i])) { 1276*18c2aff7Sartem *s++ = tolower((int)name[i]); 1277*18c2aff7Sartem } else if (rmm_vold_isbadchar((int)name[i])) { 1278*18c2aff7Sartem *s++ = '_'; 1279*18c2aff7Sartem } else { 1280*18c2aff7Sartem *s++ = name[i]; 1281*18c2aff7Sartem } 1282*18c2aff7Sartem } 1283*18c2aff7Sartem } 1284*18c2aff7Sartem *s = '\0'; 1285*18c2aff7Sartem s = strdup(buf); 1286*18c2aff7Sartem 1287*18c2aff7Sartem return (s); 1288*18c2aff7Sartem } 1289*18c2aff7Sartem 1290*18c2aff7Sartem /* 1291*18c2aff7Sartem * swiped from mkdir.c 1292*18c2aff7Sartem */ 1293*18c2aff7Sartem int 1294*18c2aff7Sartem makepath(char *dir, mode_t mode) 1295*18c2aff7Sartem { 1296*18c2aff7Sartem int err; 1297*18c2aff7Sartem char *slash; 1298*18c2aff7Sartem 1299*18c2aff7Sartem 1300*18c2aff7Sartem if ((mkdir(dir, mode) == 0) || (errno == EEXIST)) { 1301*18c2aff7Sartem return (0); 1302*18c2aff7Sartem } 1303*18c2aff7Sartem if (errno != ENOENT) { 1304*18c2aff7Sartem return (-1); 1305*18c2aff7Sartem } 1306*18c2aff7Sartem if ((slash = strrchr(dir, '/')) == NULL) { 1307*18c2aff7Sartem return (-1); 1308*18c2aff7Sartem } 1309*18c2aff7Sartem *slash = '\0'; 1310*18c2aff7Sartem err = makepath(dir, mode); 1311*18c2aff7Sartem *slash++ = '/'; 1312*18c2aff7Sartem 1313*18c2aff7Sartem if (err || (*slash == '\0')) { 1314*18c2aff7Sartem return (err); 1315*18c2aff7Sartem } 1316*18c2aff7Sartem 1317*18c2aff7Sartem return (mkdir(dir, mode)); 1318*18c2aff7Sartem } 1319*18c2aff7Sartem 1320*18c2aff7Sartem 1321*18c2aff7Sartem void 1322*18c2aff7Sartem dprintf(const char *fmt, ...) 1323*18c2aff7Sartem { 1324*18c2aff7Sartem 1325*18c2aff7Sartem va_list ap; 1326*18c2aff7Sartem const char *p; 1327*18c2aff7Sartem char msg[BUFSIZ]; 1328*18c2aff7Sartem char *errmsg = strerror(errno); 1329*18c2aff7Sartem char *s; 1330*18c2aff7Sartem 1331*18c2aff7Sartem if (rmm_debug == 0) { 1332*18c2aff7Sartem return; 1333*18c2aff7Sartem } 1334*18c2aff7Sartem 1335*18c2aff7Sartem (void) memset(msg, 0, BUFSIZ); 1336*18c2aff7Sartem 1337*18c2aff7Sartem /* scan for %m and replace with errno msg */ 1338*18c2aff7Sartem s = &msg[strlen(msg)]; 1339*18c2aff7Sartem p = fmt; 1340*18c2aff7Sartem 1341*18c2aff7Sartem while (*p != '\0') { 1342*18c2aff7Sartem if ((*p == '%') && (*(p+1) == 'm')) { 1343*18c2aff7Sartem (void) strcat(s, errmsg); 1344*18c2aff7Sartem p += 2; 1345*18c2aff7Sartem s += strlen(errmsg); 1346*18c2aff7Sartem continue; 1347*18c2aff7Sartem } 1348*18c2aff7Sartem *s++ = *p++; 1349*18c2aff7Sartem } 1350*18c2aff7Sartem *s = '\0'; /* don't forget the null byte */ 1351*18c2aff7Sartem 1352*18c2aff7Sartem va_start(ap, fmt); 1353*18c2aff7Sartem (void) vfprintf(stderr, msg, ap); 1354*18c2aff7Sartem va_end(ap); 1355*18c2aff7Sartem } 1356