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
usage(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
unknown_zpool_error(const char * detail)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
audit_pool(const adt_export_data_t * imported_state,au_event_t event_id,int result,const char * auth_used,const char * pool,const char * device)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
handle_zpool(LibHalContext * hal_ctx,LibPolKitContext * pol_ctx,char * subcmd,const char * pool,const char * device,const char * invoked_by_uid,const char * invoked_by_syscon_name,DBusConnection * system_bus)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
main(int argc,char * argv[])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