1 /*************************************************************************** 2 * 3 * hal-storage-zpool.c : ZFS pool methods 4 * 5 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 6 * Use is subject to license terms. 7 * 8 * Licensed under the Academic Free License version 2.1 9 * 10 **************************************************************************/ 11 12 #pragma ident "%Z%%M% %I% %E% SMI" 13 14 #ifdef HAVE_CONFIG_H 15 # include <config.h> 16 #endif 17 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <glib.h> 22 #include <glib/gstdio.h> 23 #include <sys/types.h> 24 #include <wait.h> 25 #include <unistd.h> 26 #include <bsm/adt.h> 27 #include <bsm/adt_event.h> 28 29 #include <libhal.h> 30 #include <libhal-storage.h> 31 #ifdef HAVE_POLKIT 32 #include <libpolkit.h> 33 #endif 34 35 #include "hal-storage-shared.h" 36 37 static void 38 usage (void) 39 { 40 fprintf (stderr, "This program should only be started by hald.\n"); 41 exit (1); 42 } 43 44 45 void static 46 unknown_zpool_error (const char *detail) 47 { 48 fprintf (stderr, "org.freedesktop.Hal.Device.Volume.UnknownFailure\n"); 49 fprintf (stderr, "%s\n", detail); 50 exit (1); 51 } 52 53 void 54 audit_pool(const adt_export_data_t *imported_state, au_event_t event_id, 55 int result, const char *auth_used, const char *pool, const char *device) 56 { 57 adt_session_data_t *ah; 58 adt_event_data_t *event; 59 60 if (adt_start_session(&ah, imported_state, 0) != 0) { 61 printf ("adt_start_session failed %d\n", errno); 62 return; 63 } 64 if ((event = adt_alloc_event(ah, event_id)) == NULL) { 65 printf ("adt_alloc_event(ADT_attach)\n", errno); 66 return; 67 } 68 69 switch (event_id) { 70 case ADT_pool_export: 71 event->adt_pool_export.auth_used = (char *)auth_used; 72 event->adt_pool_export.pool = (char *)pool; 73 event->adt_pool_export.device = (char *)device; 74 break; 75 case ADT_pool_import: 76 event->adt_pool_import.auth_used = (char *)auth_used; 77 event->adt_pool_import.pool = (char *)pool; 78 event->adt_pool_import.device = (char *)device; 79 break; 80 default: 81 goto out; 82 } 83 84 if (result == 0) { 85 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 86 printf ("adt_put_event(%d, success)\n", event_id); 87 } 88 } else { 89 if (adt_put_event(event, ADT_FAILURE, result) != 0) { 90 printf ("adt_put_event(%d, failure)\n", event_id); 91 } 92 } 93 out: 94 adt_free_event(event); 95 (void) adt_end_session(ah); 96 } 97 98 99 void 100 handle_zpool (LibHalContext *hal_ctx, 101 #ifdef HAVE_POLKIT 102 LibPolKitContext *pol_ctx, 103 #endif 104 char *subcmd, const char *pool, const char *device, 105 const char *invoked_by_uid, const char *invoked_by_syscon_name, 106 DBusConnection *system_bus) 107 { 108 GError *err = NULL; 109 char *sout = NULL; 110 char *serr = NULL; 111 int exit_status = 0; 112 char *args[10]; 113 int na; 114 adt_export_data_t *adt_data; 115 size_t adt_data_size; 116 au_event_t event_id; 117 118 #ifdef DEBUG 119 printf ("subcmd = %s\n", subcmd); 120 printf ("pool = %s\n", pool); 121 printf ("device = %s\n", device); 122 printf ("invoked by uid = %s\n", invoked_by_uid); 123 printf ("invoked by system bus connection = %s\n", invoked_by_syscon_name); 124 #endif 125 126 na = 0; 127 args[na++] = "/usr/sbin/zpool"; 128 args[na++] = subcmd; 129 if ((strcmp (subcmd, "import") == 0) && 130 (strncmp (device, "/dev/lofi", 9) == 0)) { 131 args[na++] = "-d"; 132 args[na++] = "/dev/lofi"; 133 } 134 args[na++] = (char *) pool; 135 args[na++] = NULL; 136 137 /* invoke eject command */ 138 if (!g_spawn_sync ("/", 139 args, 140 NULL, 141 0, 142 NULL, 143 NULL, 144 &sout, 145 &serr, 146 &exit_status, 147 &err)) { 148 printf ("Cannot execute zpool %s\n", subcmd); 149 unknown_zpool_error ("Cannot spawn zpool"); 150 } 151 152 if ((adt_data = get_audit_export_data (system_bus, 153 invoked_by_syscon_name, &adt_data_size)) != NULL) { 154 event_id = (strcmp (subcmd, "import") == 0) ? 155 ADT_pool_import : ADT_pool_export; 156 audit_pool (adt_data, event_id, WEXITSTATUS(exit_status), 157 "solaris.device.mount.removable", pool, device); 158 free (adt_data); 159 } 160 161 if (exit_status != 0) { 162 printf ("zpool error %d, stdout='%s', stderr='%s'\n", exit_status, sout, serr); 163 164 unknown_zpool_error (serr); 165 } 166 167 g_free (sout); 168 g_free (serr); 169 } 170 171 172 int 173 main (int argc, char *argv[]) 174 { 175 char *udi; 176 char *device; 177 const char *drive_udi; 178 LibHalDrive *drive; 179 LibHalVolume *volume; 180 DBusError error; 181 LibHalContext *hal_ctx = NULL; 182 DBusConnection *system_bus = NULL; 183 #ifdef HAVE_POLKIT 184 LibPolKitContext *pol_ctx = NULL; 185 #endif 186 char *invoked_by_uid; 187 char *invoked_by_syscon_name; 188 189 device = getenv ("HAL_PROP_BLOCK_DEVICE"); 190 if (device == NULL) 191 usage (); 192 193 udi = getenv ("HAL_PROP_INFO_UDI"); 194 if (udi == NULL) 195 usage (); 196 197 invoked_by_uid = getenv ("HAL_METHOD_INVOKED_BY_UID"); 198 199 invoked_by_syscon_name = getenv ("HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME"); 200 201 dbus_error_init (&error); 202 if ((hal_ctx = libhal_ctx_init_direct (&error)) == NULL) { 203 printf ("Cannot connect to hald\n"); 204 LIBHAL_FREE_DBUS_ERROR (&error); 205 usage (); 206 } 207 208 dbus_error_init (&error); 209 system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error); 210 if (system_bus == NULL) { 211 printf ("Cannot connect to the system bus\n"); 212 LIBHAL_FREE_DBUS_ERROR (&error); 213 usage (); 214 } 215 #ifdef HAVE_POLKIT 216 pol_ctx = libpolkit_new_context (system_bus); 217 if (pol_ctx == NULL) { 218 printf ("Cannot get libpolkit context\n"); 219 unknown_zpool_error ("Cannot get libpolkit context"); 220 } 221 #endif 222 223 /* should be a volume */ 224 if ((volume = libhal_volume_from_udi (hal_ctx, udi)) == NULL) { 225 unknown_zpool_error ("Invalid volume"); 226 } 227 if ((drive_udi = libhal_volume_get_storage_device_udi (volume)) == NULL ) { 228 unknown_zpool_error ("Cannot get drive udi"); 229 } 230 if ((drive = libhal_drive_from_udi (hal_ctx, drive_udi)) == NULL) { 231 unknown_zpool_error ("Cannot get drive from udi"); 232 } 233 if ((libhal_volume_get_fstype (volume) == NULL) || 234 (strcmp (libhal_volume_get_fstype (volume), "zfs") != 0)) { 235 unknown_zpool_error ("Not a zpool"); 236 } 237 if ((libhal_volume_get_label (volume) == NULL) || 238 (strlen (libhal_volume_get_label (volume)) == 0)) { 239 unknown_zpool_error ("Invalid zpool name"); 240 } 241 242 handle_zpool (hal_ctx, 243 #ifdef HAVE_POLKIT 244 pol_ctx, 245 #endif 246 ZPOOL_SUBCMD, 247 libhal_volume_get_label (volume), 248 device, 249 invoked_by_uid, 250 invoked_by_syscon_name, 251 system_bus); 252 253 return 0; 254 } 255 256