118c2aff7Sartem /***************************************************************************
218c2aff7Sartem  *
318c2aff7Sartem  * hal-storage-zpool.c : ZFS pool methods
418c2aff7Sartem  *
518c2aff7Sartem  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
618c2aff7Sartem  * Use is subject to license terms.
718c2aff7Sartem  *
818c2aff7Sartem  * Licensed under the Academic Free License version 2.1
918c2aff7Sartem  *
1018c2aff7Sartem  **************************************************************************/
1118c2aff7Sartem 
1218c2aff7Sartem #ifdef HAVE_CONFIG_H
1318c2aff7Sartem #  include <config.h>
1418c2aff7Sartem #endif
1518c2aff7Sartem 
1618c2aff7Sartem #include <stdio.h>
1718c2aff7Sartem #include <stdlib.h>
1818c2aff7Sartem #include <string.h>
1918c2aff7Sartem #include <glib.h>
2018c2aff7Sartem #include <glib/gstdio.h>
2118c2aff7Sartem #include <sys/types.h>
2218c2aff7Sartem #include <wait.h>
2318c2aff7Sartem #include <unistd.h>
2418c2aff7Sartem #include <bsm/adt.h>
2518c2aff7Sartem #include <bsm/adt_event.h>
2618c2aff7Sartem 
2718c2aff7Sartem #include <libhal.h>
2818c2aff7Sartem #include <libhal-storage.h>
2918c2aff7Sartem #ifdef HAVE_POLKIT
3018c2aff7Sartem #include <libpolkit.h>
3118c2aff7Sartem #endif
3218c2aff7Sartem 
3318c2aff7Sartem #include "hal-storage-shared.h"
3418c2aff7Sartem 
3518c2aff7Sartem static void
usage(void)3618c2aff7Sartem usage (void)
3718c2aff7Sartem {
3818c2aff7Sartem 	fprintf (stderr, "This program should only be started by hald.\n");
3918c2aff7Sartem 	exit (1);
4018c2aff7Sartem }
4118c2aff7Sartem 
4218c2aff7Sartem 
4318c2aff7Sartem void static
unknown_zpool_error(const char * detail)4418c2aff7Sartem unknown_zpool_error (const char *detail)
4518c2aff7Sartem {
4618c2aff7Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.Volume.UnknownFailure\n");
4718c2aff7Sartem 	fprintf (stderr, "%s\n", detail);
4818c2aff7Sartem 	exit (1);
4918c2aff7Sartem }
5018c2aff7Sartem 
5118c2aff7Sartem 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)5218c2aff7Sartem audit_pool(const adt_export_data_t *imported_state, au_event_t event_id,
5318c2aff7Sartem     int result, const char *auth_used, const char *pool, const char *device)
5418c2aff7Sartem {
5518c2aff7Sartem 	adt_session_data_t      *ah;
5618c2aff7Sartem 	adt_event_data_t        *event;
5718c2aff7Sartem 
5818c2aff7Sartem 	if (adt_start_session(&ah, imported_state, 0) != 0) {
5918c2aff7Sartem         	printf ("adt_start_session failed %d\n", errno);
6018c2aff7Sartem         	return;
6118c2aff7Sartem 	}
6218c2aff7Sartem 	if ((event = adt_alloc_event(ah, event_id)) == NULL) {
6318c2aff7Sartem         	printf ("adt_alloc_event(ADT_attach)\n", errno);
6418c2aff7Sartem         	return;
6518c2aff7Sartem 	}
6618c2aff7Sartem 
6718c2aff7Sartem 	switch (event_id) {
6818c2aff7Sartem 	case ADT_pool_export:
6918c2aff7Sartem 		event->adt_pool_export.auth_used = (char *)auth_used;
7018c2aff7Sartem 		event->adt_pool_export.pool = (char *)pool;
7118c2aff7Sartem 		event->adt_pool_export.device = (char *)device;
7218c2aff7Sartem 		break;
7318c2aff7Sartem 	case ADT_pool_import:
7418c2aff7Sartem 		event->adt_pool_import.auth_used = (char *)auth_used;
7518c2aff7Sartem 		event->adt_pool_import.pool = (char *)pool;
7618c2aff7Sartem 		event->adt_pool_import.device = (char *)device;
7718c2aff7Sartem 		break;
7818c2aff7Sartem 	default:
7918c2aff7Sartem 		goto out;
8018c2aff7Sartem 	}
8118c2aff7Sartem 
8218c2aff7Sartem 	if (result == 0) {
8318c2aff7Sartem 		if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
8418c2aff7Sartem 			printf ("adt_put_event(%d, success)\n", event_id);
8518c2aff7Sartem 		}
8618c2aff7Sartem 	} else {
8718c2aff7Sartem 		if (adt_put_event(event, ADT_FAILURE, result) != 0) {
8818c2aff7Sartem 			printf ("adt_put_event(%d, failure)\n", event_id);
8918c2aff7Sartem 		}
9018c2aff7Sartem 	}
9118c2aff7Sartem out:
9218c2aff7Sartem 	adt_free_event(event);
9318c2aff7Sartem 	(void) adt_end_session(ah);
9418c2aff7Sartem }
9518c2aff7Sartem 
9618c2aff7Sartem 
9718c2aff7Sartem 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)98*2a8bcb4eSToomas Soome handle_zpool (LibHalContext *hal_ctx,
9918c2aff7Sartem #ifdef HAVE_POLKIT
100*2a8bcb4eSToomas Soome 	      LibPolKitContext *pol_ctx,
10118c2aff7Sartem #endif
10218c2aff7Sartem 	      char *subcmd, const char *pool, const char *device,
10318c2aff7Sartem 	      const char *invoked_by_uid, const char *invoked_by_syscon_name,
10418c2aff7Sartem 	      DBusConnection *system_bus)
10518c2aff7Sartem {
10618c2aff7Sartem 	GError *err = NULL;
10718c2aff7Sartem 	char *sout = NULL;
10818c2aff7Sartem 	char *serr = NULL;
10918c2aff7Sartem 	int exit_status = 0;
11018c2aff7Sartem 	char *args[10];
11118c2aff7Sartem 	int na;
11218c2aff7Sartem 	adt_export_data_t *adt_data;
11318c2aff7Sartem 	size_t adt_data_size;
11418c2aff7Sartem 	au_event_t event_id;
11518c2aff7Sartem 
11618c2aff7Sartem #ifdef DEBUG
11718c2aff7Sartem 	printf ("subcmd                           = %s\n", subcmd);
11818c2aff7Sartem 	printf ("pool                             = %s\n", pool);
11918c2aff7Sartem 	printf ("device                           = %s\n", device);
12018c2aff7Sartem 	printf ("invoked by uid                   = %s\n", invoked_by_uid);
12118c2aff7Sartem 	printf ("invoked by system bus connection = %s\n", invoked_by_syscon_name);
12218c2aff7Sartem #endif
12318c2aff7Sartem 
12418c2aff7Sartem 	na = 0;
12518c2aff7Sartem 	args[na++] = "/usr/sbin/zpool";
12618c2aff7Sartem 	args[na++] = subcmd;
12718c2aff7Sartem 	if ((strcmp (subcmd, "import") == 0) &&
12818c2aff7Sartem 	    (strncmp (device, "/dev/lofi", 9) == 0)) {
12918c2aff7Sartem 		args[na++] = "-d";
13018c2aff7Sartem 		args[na++] = "/dev/lofi";
13118c2aff7Sartem 	}
13218c2aff7Sartem 	args[na++] = (char *) pool;
13318c2aff7Sartem 	args[na++] = NULL;
13418c2aff7Sartem 
13518c2aff7Sartem 	/* invoke eject command */
13618c2aff7Sartem 	if (!g_spawn_sync ("/",
13718c2aff7Sartem 			   args,
13818c2aff7Sartem 			   NULL,
13918c2aff7Sartem 			   0,
14018c2aff7Sartem 			   NULL,
14118c2aff7Sartem 			   NULL,
14218c2aff7Sartem 			   &sout,
14318c2aff7Sartem 			   &serr,
14418c2aff7Sartem 			   &exit_status,
14518c2aff7Sartem 			   &err)) {
14618c2aff7Sartem 		printf ("Cannot execute zpool %s\n", subcmd);
14718c2aff7Sartem 		unknown_zpool_error ("Cannot spawn zpool");
14818c2aff7Sartem 	}
14918c2aff7Sartem 
15018c2aff7Sartem 	if ((adt_data = get_audit_export_data (system_bus,
15118c2aff7Sartem 	    invoked_by_syscon_name, &adt_data_size)) != NULL) {
15218c2aff7Sartem 		event_id = (strcmp (subcmd, "import") == 0) ?
15318c2aff7Sartem 		    ADT_pool_import : ADT_pool_export;
15418c2aff7Sartem 		audit_pool (adt_data, event_id, WEXITSTATUS(exit_status),
15518c2aff7Sartem 		    "solaris.device.mount.removable", pool, device);
15618c2aff7Sartem 		free (adt_data);
15718c2aff7Sartem 	}
15818c2aff7Sartem 
15918c2aff7Sartem 	if (exit_status != 0) {
16018c2aff7Sartem 		printf ("zpool error %d, stdout='%s', stderr='%s'\n", exit_status, sout, serr);
16118c2aff7Sartem 
16218c2aff7Sartem 		unknown_zpool_error (serr);
16318c2aff7Sartem 	}
16418c2aff7Sartem 
16518c2aff7Sartem 	g_free (sout);
16618c2aff7Sartem 	g_free (serr);
16718c2aff7Sartem }
16818c2aff7Sartem 
16918c2aff7Sartem 
17018c2aff7Sartem int
main(int argc,char * argv[])17118c2aff7Sartem main (int argc, char *argv[])
17218c2aff7Sartem {
17318c2aff7Sartem 	char *udi;
17418c2aff7Sartem 	char *device;
17518c2aff7Sartem 	const char *drive_udi;
17618c2aff7Sartem 	LibHalDrive *drive;
17718c2aff7Sartem 	LibHalVolume *volume;
17818c2aff7Sartem 	DBusError error;
17918c2aff7Sartem 	LibHalContext *hal_ctx = NULL;
18018c2aff7Sartem 	DBusConnection *system_bus = NULL;
18118c2aff7Sartem #ifdef HAVE_POLKIT
18218c2aff7Sartem 	LibPolKitContext *pol_ctx = NULL;
18318c2aff7Sartem #endif
18418c2aff7Sartem 	char *invoked_by_uid;
18518c2aff7Sartem 	char *invoked_by_syscon_name;
18618c2aff7Sartem 
18718c2aff7Sartem 	device = getenv ("HAL_PROP_BLOCK_DEVICE");
18818c2aff7Sartem 	if (device == NULL)
18918c2aff7Sartem 		usage ();
19018c2aff7Sartem 
19118c2aff7Sartem 	udi = getenv ("HAL_PROP_INFO_UDI");
19218c2aff7Sartem 	if (udi == NULL)
19318c2aff7Sartem 		usage ();
19418c2aff7Sartem 
19518c2aff7Sartem 	invoked_by_uid = getenv ("HAL_METHOD_INVOKED_BY_UID");
19618c2aff7Sartem 
19718c2aff7Sartem 	invoked_by_syscon_name = getenv ("HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME");
19818c2aff7Sartem 
19918c2aff7Sartem 	dbus_error_init (&error);
20018c2aff7Sartem 	if ((hal_ctx = libhal_ctx_init_direct (&error)) == NULL) {
20118c2aff7Sartem 		printf ("Cannot connect to hald\n");
20218c2aff7Sartem 		LIBHAL_FREE_DBUS_ERROR (&error);
20318c2aff7Sartem 		usage ();
20418c2aff7Sartem 	}
20518c2aff7Sartem 
20618c2aff7Sartem 	dbus_error_init (&error);
20718c2aff7Sartem 	system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
20818c2aff7Sartem 	if (system_bus == NULL) {
20918c2aff7Sartem 		printf ("Cannot connect to the system bus\n");
21018c2aff7Sartem 		LIBHAL_FREE_DBUS_ERROR (&error);
21118c2aff7Sartem 		usage ();
21218c2aff7Sartem 	}
21318c2aff7Sartem #ifdef HAVE_POLKIT
21418c2aff7Sartem 	pol_ctx = libpolkit_new_context (system_bus);
21518c2aff7Sartem 	if (pol_ctx == NULL) {
21618c2aff7Sartem 		printf ("Cannot get libpolkit context\n");
21718c2aff7Sartem 		unknown_zpool_error ("Cannot get libpolkit context");
21818c2aff7Sartem 	}
21918c2aff7Sartem #endif
22018c2aff7Sartem 
22118c2aff7Sartem 	/* should be a volume */
22218c2aff7Sartem 	if ((volume = libhal_volume_from_udi (hal_ctx, udi)) == NULL) {
22318c2aff7Sartem 		unknown_zpool_error ("Invalid volume");
22418c2aff7Sartem 	}
22518c2aff7Sartem 	if ((drive_udi = libhal_volume_get_storage_device_udi (volume)) == NULL ) {
22618c2aff7Sartem 		unknown_zpool_error ("Cannot get drive udi");
22718c2aff7Sartem 	}
22818c2aff7Sartem 	if ((drive = libhal_drive_from_udi (hal_ctx, drive_udi)) == NULL) {
22918c2aff7Sartem 		unknown_zpool_error ("Cannot get drive from udi");
23018c2aff7Sartem 	}
23118c2aff7Sartem 	if ((libhal_volume_get_fstype (volume) == NULL) ||
23218c2aff7Sartem 	    (strcmp (libhal_volume_get_fstype (volume), "zfs") != 0)) {
23318c2aff7Sartem 		unknown_zpool_error ("Not a zpool");
23418c2aff7Sartem 	}
23518c2aff7Sartem 	if ((libhal_volume_get_label (volume) == NULL) ||
23618c2aff7Sartem 	    (strlen (libhal_volume_get_label (volume)) == 0)) {
23718c2aff7Sartem 		unknown_zpool_error ("Invalid zpool name");
23818c2aff7Sartem 	}
23918c2aff7Sartem 
24018c2aff7Sartem         handle_zpool (hal_ctx,
24118c2aff7Sartem #ifdef HAVE_POLKIT
24218c2aff7Sartem 		      pol_ctx,
24318c2aff7Sartem #endif
24418c2aff7Sartem                       ZPOOL_SUBCMD,
24518c2aff7Sartem                       libhal_volume_get_label (volume),
24618c2aff7Sartem 		      device,
24718c2aff7Sartem                       invoked_by_uid,
24818c2aff7Sartem                       invoked_by_syscon_name,
24918c2aff7Sartem 		      system_bus);
25018c2aff7Sartem 
25118c2aff7Sartem 	return 0;
25218c2aff7Sartem }
25318c2aff7Sartem 
254