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