xref: /illumos-gate/usr/src/cmd/hal/tools/hal-storage-zpool.c (revision 4c87aefe8930bd07275b8dd2e96ea5f24d93a52e)
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