xref: /titanic_41/usr/src/cmd/hal/tools/hal-storage-shared.c (revision 7b1f4223d0637b428ed4e46b5bc295f7a949e670)
118c2aff7Sartem /***************************************************************************
218c2aff7Sartem  * CVSID: $Id: hal-storage-mount.c,v 1.7 2006/06/21 00:44:03 david Exp $
318c2aff7Sartem  *
418c2aff7Sartem  * hal-storage-mount.c : Mount wrapper
518c2aff7Sartem  *
618c2aff7Sartem  * Copyright (C) 2006 David Zeuthen, <david@fubar.dk>
718c2aff7Sartem  *
818c2aff7Sartem  * This program is free software; you can redistribute it and/or modify
918c2aff7Sartem  * it under the terms of the GNU General Public License as published by
1018c2aff7Sartem  * the Free Software Foundation; either version 2 of the License, or
1118c2aff7Sartem  * (at your option) any later version.
1218c2aff7Sartem  *
1318c2aff7Sartem  * This program is distributed in the hope that it will be useful,
1418c2aff7Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1518c2aff7Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1618c2aff7Sartem  * GNU General Public License for more details.
1718c2aff7Sartem  *
1818c2aff7Sartem  * You should have received a copy of the GNU General Public License
1918c2aff7Sartem  * along with this program; if not, write to the Free Software
2018c2aff7Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2118c2aff7Sartem  *
2218c2aff7Sartem  **************************************************************************/
2318c2aff7Sartem 
2418c2aff7Sartem 
2518c2aff7Sartem #ifdef HAVE_CONFIG_H
2618c2aff7Sartem #  include <config.h>
2718c2aff7Sartem #endif
2818c2aff7Sartem 
2918c2aff7Sartem #include <stdio.h>
3018c2aff7Sartem #include <stdlib.h>
3118c2aff7Sartem #include <string.h>
3218c2aff7Sartem #include <glib.h>
3318c2aff7Sartem #include <glib/gstdio.h>
3418c2aff7Sartem #ifdef __FreeBSD__
3518c2aff7Sartem #include <fstab.h>
3618c2aff7Sartem #include <sys/param.h>
3718c2aff7Sartem #include <sys/ucred.h>
3818c2aff7Sartem #include <sys/mount.h>
3918c2aff7Sartem #include <limits.h>
4018c2aff7Sartem #include <pwd.h>
4118c2aff7Sartem #elif sun
4218c2aff7Sartem #include <fcntl.h>
4318c2aff7Sartem #include <sys/mnttab.h>
4418c2aff7Sartem #include <sys/vfstab.h>
4518c2aff7Sartem #include <sys/stat.h>
4618c2aff7Sartem #include <sys/wait.h>
4718c2aff7Sartem #include <bsm/adt.h>
4818c2aff7Sartem #include <bsm/adt_event.h>
4918c2aff7Sartem #else
5018c2aff7Sartem #include <mntent.h>
5118c2aff7Sartem #endif
5218c2aff7Sartem #include <sys/types.h>
5318c2aff7Sartem #include <unistd.h>
5418c2aff7Sartem #include <sys/file.h>
5518c2aff7Sartem #include <errno.h>
5618c2aff7Sartem #include <syslog.h>
5718c2aff7Sartem 
5818c2aff7Sartem #include "hal-storage-shared.h"
5918c2aff7Sartem 
6018c2aff7Sartem #ifdef __FreeBSD__
6118c2aff7Sartem struct mtab_handle
6218c2aff7Sartem {
6318c2aff7Sartem   struct statfs	*mounts;
6418c2aff7Sartem   int		n_mounts;
6518c2aff7Sartem   int		iter;
6618c2aff7Sartem };
6718c2aff7Sartem #endif
6818c2aff7Sartem 
6918c2aff7Sartem 
7018c2aff7Sartem gboolean
mtab_open(gpointer * handle)7118c2aff7Sartem mtab_open (gpointer *handle)
7218c2aff7Sartem {
7318c2aff7Sartem #ifdef __FreeBSD__
7418c2aff7Sartem 	struct mtab_handle *mtab;
7518c2aff7Sartem 
7618c2aff7Sartem 	mtab = g_new0 (struct mtab_handle, 1);
7718c2aff7Sartem 	mtab->n_mounts = getmntinfo (&mtab->mounts, MNT_NOWAIT);
7818c2aff7Sartem 	if (mtab->n_mounts == 0) {
7918c2aff7Sartem 		g_free (mtab);
8018c2aff7Sartem 		return FALSE;
8118c2aff7Sartem 	}
8218c2aff7Sartem 
8318c2aff7Sartem 	*handle = mtab;
8418c2aff7Sartem 	return TRUE;
8518c2aff7Sartem #elif sun
8618c2aff7Sartem 	*handle = fopen (MNTTAB, "r");
8718c2aff7Sartem 	return *handle != NULL;
8818c2aff7Sartem #else
8918c2aff7Sartem 	*handle = fopen ("/proc/mounts", "r");
9018c2aff7Sartem 	return *handle != NULL;
9118c2aff7Sartem #endif
9218c2aff7Sartem }
9318c2aff7Sartem 
9418c2aff7Sartem char *
mtab_next(gpointer handle,char ** mount_point)9518c2aff7Sartem mtab_next (gpointer handle, char **mount_point)
9618c2aff7Sartem {
9718c2aff7Sartem #ifdef __FreeBSD__
9818c2aff7Sartem 	struct mtab_handle *mtab = handle;
9918c2aff7Sartem 
10018c2aff7Sartem 	if (mtab->iter < mtab->n_mounts)
10118c2aff7Sartem 		return mtab->mounts[mtab->iter++].f_mntfromname;
10218c2aff7Sartem 	else
10318c2aff7Sartem 		return NULL;
10418c2aff7Sartem #error TODO: set *mount_point to g_strdup()-ed value if mount_point!=NULL
10518c2aff7Sartem #elif sun
10618c2aff7Sartem 	static struct mnttab mnt;
10718c2aff7Sartem 
10818c2aff7Sartem 	if (getmntent (handle, &mnt) == 0) {
10918c2aff7Sartem 		if (mount_point != NULL) {
11018c2aff7Sartem 			*mount_point = g_strdup (mnt.mnt_mountp);
11118c2aff7Sartem 		}
11218c2aff7Sartem 		return mnt.mnt_special;
11318c2aff7Sartem 	} else {
11418c2aff7Sartem 		return NULL;
11518c2aff7Sartem 	}
11618c2aff7Sartem #else
11718c2aff7Sartem 	struct mntent *mnt;
11818c2aff7Sartem 
11918c2aff7Sartem 	mnt = getmntent (handle);
12018c2aff7Sartem 
12118c2aff7Sartem 	if (mnt != NULL) {
12218c2aff7Sartem 		if (mount_point != NULL) {
12318c2aff7Sartem 			*mount_point = g_strdup (mnt->mnt_dir);
12418c2aff7Sartem 		}
12518c2aff7Sartem 		return mnt->mnt_fsname;
12618c2aff7Sartem 	} else {
12718c2aff7Sartem 		return NULL;
12818c2aff7Sartem 	}
12918c2aff7Sartem #endif
13018c2aff7Sartem }
13118c2aff7Sartem 
13218c2aff7Sartem void
mtab_close(gpointer handle)13318c2aff7Sartem mtab_close (gpointer handle)
13418c2aff7Sartem {
13518c2aff7Sartem #ifdef __FreeBSD__
13618c2aff7Sartem 	g_free (handle);
13718c2aff7Sartem #else
13818c2aff7Sartem 	fclose (handle);
13918c2aff7Sartem #endif
14018c2aff7Sartem }
14118c2aff7Sartem 
14218c2aff7Sartem 
14318c2aff7Sartem 
14418c2aff7Sartem gboolean
fstab_open(gpointer * handle)14518c2aff7Sartem fstab_open (gpointer *handle)
14618c2aff7Sartem {
14718c2aff7Sartem #ifdef __FreeBSD__
14818c2aff7Sartem 	return setfsent () == 1;
14918c2aff7Sartem #elif sun
15018c2aff7Sartem 	*handle = fopen (VFSTAB, "r");
15118c2aff7Sartem 	return *handle != NULL;
15218c2aff7Sartem #else
15318c2aff7Sartem 	*handle = fopen ("/etc/fstab", "r");
15418c2aff7Sartem 	return *handle != NULL;
15518c2aff7Sartem #endif
15618c2aff7Sartem }
15718c2aff7Sartem 
15818c2aff7Sartem char *
fstab_next(gpointer handle,char ** mount_point)15918c2aff7Sartem fstab_next (gpointer handle, char **mount_point)
16018c2aff7Sartem {
16118c2aff7Sartem #ifdef __FreeBSD__
16218c2aff7Sartem 	struct fstab *fstab;
16318c2aff7Sartem 
16418c2aff7Sartem 	fstab = getfsent ();
16518c2aff7Sartem 
16618c2aff7Sartem 	/* TODO: fill out mount_point */
16718c2aff7Sartem 	if (mount_point != NULL && fstab != NULL) {
16818c2aff7Sartem 		*mount_point = fstab->fs_file;
16918c2aff7Sartem 	}
17018c2aff7Sartem 
17118c2aff7Sartem 	return fstab ? fstab->fs_spec : NULL;
17218c2aff7Sartem #elif sun
17318c2aff7Sartem 	static struct vfstab v;
17418c2aff7Sartem 
17518c2aff7Sartem 	return getvfsent (handle, &v) == 0 ? v.vfs_special : NULL;
17618c2aff7Sartem #else
17718c2aff7Sartem 	struct mntent *mnt;
17818c2aff7Sartem 
17918c2aff7Sartem 	mnt = getmntent (handle);
18018c2aff7Sartem 
18118c2aff7Sartem 	if (mount_point != NULL && mnt != NULL) {
18218c2aff7Sartem 		*mount_point = mnt->mnt_dir;
18318c2aff7Sartem 	}
18418c2aff7Sartem 
18518c2aff7Sartem 	return mnt ? mnt->mnt_fsname : NULL;
18618c2aff7Sartem #endif
18718c2aff7Sartem }
18818c2aff7Sartem 
18918c2aff7Sartem void
fstab_close(gpointer handle)19018c2aff7Sartem fstab_close (gpointer handle)
19118c2aff7Sartem {
19218c2aff7Sartem #ifdef __FreeBSD__
19318c2aff7Sartem 	endfsent ();
19418c2aff7Sartem #else
19518c2aff7Sartem 	fclose (handle);
19618c2aff7Sartem #endif
19718c2aff7Sartem }
19818c2aff7Sartem 
19918c2aff7Sartem #ifdef __FreeBSD__
20018c2aff7Sartem #define UMOUNT		"/sbin/umount"
20118c2aff7Sartem #elif sun
20218c2aff7Sartem #define UMOUNT		"/sbin/umount"
20318c2aff7Sartem #else
20418c2aff7Sartem #define UMOUNT		"/bin/umount"
20518c2aff7Sartem #endif
20618c2aff7Sartem 
20718c2aff7Sartem void
unknown_error(const char * detail)20818c2aff7Sartem unknown_error (const char *detail)
20918c2aff7Sartem {
21018c2aff7Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.Volume.UnknownFailure\n");
21118c2aff7Sartem 	fprintf (stderr, "%s\n", detail);
21218c2aff7Sartem 	exit (1);
21318c2aff7Sartem }
21418c2aff7Sartem 
21518c2aff7Sartem 
21618c2aff7Sartem static void
device_busy(const char * detail)21718c2aff7Sartem device_busy (const char *detail)
21818c2aff7Sartem {
21918c2aff7Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.Volume.Busy\n");
22018c2aff7Sartem 	fprintf (stderr, "%s\n", detail);
22118c2aff7Sartem 	exit (1);
22218c2aff7Sartem }
22318c2aff7Sartem 
22418c2aff7Sartem 
22518c2aff7Sartem static void
not_mounted(const char * detail)22618c2aff7Sartem not_mounted (const char *detail)
22718c2aff7Sartem {
22818c2aff7Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.Volume.NotMounted\n");
22918c2aff7Sartem 	fprintf (stderr, "%s\n", detail);
23018c2aff7Sartem 	exit (1);
23118c2aff7Sartem }
23218c2aff7Sartem 
23318c2aff7Sartem 
23418c2aff7Sartem static void
not_mounted_by_hal(const char * detail)23518c2aff7Sartem not_mounted_by_hal (const char *detail)
23618c2aff7Sartem {
23718c2aff7Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.Volume.NotMountedByHal\n");
23818c2aff7Sartem 	fprintf (stderr, "%s\n", detail);
23918c2aff7Sartem 	exit (1);
24018c2aff7Sartem }
24118c2aff7Sartem 
24218c2aff7Sartem static void
permission_denied_privilege(const char * privilege,const char * uid)24318c2aff7Sartem permission_denied_privilege (const char *privilege, const char *uid)
24418c2aff7Sartem {
24518c2aff7Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.PermissionDeniedByPolicy\n");
24618c2aff7Sartem 	fprintf (stderr, "%s refused uid %s\n", privilege, uid);
24718c2aff7Sartem 	exit (1);
24818c2aff7Sartem }
24918c2aff7Sartem 
25018c2aff7Sartem static void
permission_denied_volume_ignore(const char * device)25118c2aff7Sartem permission_denied_volume_ignore (const char *device)
25218c2aff7Sartem {
25318c2aff7Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.Volume.PermissionDenied\n");
25418c2aff7Sartem 	fprintf (stderr, "Device has %s volume.ignore set to TRUE. Refusing to mount.\n", device);
25518c2aff7Sartem 	exit (1);
25618c2aff7Sartem }
25718c2aff7Sartem 
25818c2aff7Sartem void
handle_unmount(LibHalContext * hal_ctx,LibPolKitContext * pol_ctx,const char * udi,LibHalVolume * volume,LibHalDrive * drive,const char * device,const char * invoked_by_uid,const char * invoked_by_syscon_name,gboolean option_lazy,gboolean option_force,DBusConnection * system_bus)25918c2aff7Sartem handle_unmount (LibHalContext *hal_ctx,
26018c2aff7Sartem #ifdef HAVE_POLKIT
26118c2aff7Sartem 		LibPolKitContext *pol_ctx,
26218c2aff7Sartem #endif
26318c2aff7Sartem 		const char *udi,
26418c2aff7Sartem 		LibHalVolume *volume, LibHalDrive *drive, const char *device,
26518c2aff7Sartem 		const char *invoked_by_uid, const char *invoked_by_syscon_name,
26618c2aff7Sartem 		gboolean option_lazy, gboolean option_force,
26718c2aff7Sartem 		DBusConnection *system_bus)
26818c2aff7Sartem {
26918c2aff7Sartem 	int i, j;
27018c2aff7Sartem 	DBusError error;
27118c2aff7Sartem 	GError *err = NULL;
27218c2aff7Sartem 	char *sout = NULL;
27318c2aff7Sartem 	char *serr = NULL;
27418c2aff7Sartem 	int exit_status;
27518c2aff7Sartem 	char *args[10];
27618c2aff7Sartem 	int na;
27718c2aff7Sartem 	FILE *hal_mtab_orig;
27818c2aff7Sartem 	int hal_mtab_orig_len;
27918c2aff7Sartem 	int num_read;
28018c2aff7Sartem 	char *hal_mtab_buf;
28118c2aff7Sartem 	char **lines;
28218c2aff7Sartem 	char *mount_point_to_unmount;
28318c2aff7Sartem 	gboolean mounted_by_other_uid;
28418c2aff7Sartem 	FILE *hal_mtab_new;
28518c2aff7Sartem #ifdef sun
28618c2aff7Sartem 	adt_export_data_t *adt_data;
28718c2aff7Sartem 	size_t adt_data_size;
28818c2aff7Sartem #endif
28918c2aff7Sartem 
29018c2aff7Sartem #ifdef DEBUG
29118c2aff7Sartem 	printf ("device                           = %s\n", device);
29218c2aff7Sartem 	printf ("invoked by uid                   = %s\n", invoked_by_uid);
29318c2aff7Sartem 	printf ("invoked by system bus connection = %s\n", invoked_by_syscon_name);
29418c2aff7Sartem #endif
29518c2aff7Sartem 
29618c2aff7Sartem 	if (volume != NULL) {
29718c2aff7Sartem 		dbus_error_init (&error);
29818c2aff7Sartem 		if (libhal_device_get_property_bool (hal_ctx, udi, "volume.ignore", &error) ||
29918c2aff7Sartem 		    dbus_error_is_set (&error)) {
30018c2aff7Sartem 			if (dbus_error_is_set (&error)) {
30118c2aff7Sartem 				LIBHAL_FREE_DBUS_ERROR (&error);
30218c2aff7Sartem 			}
30318c2aff7Sartem 			/*
30418c2aff7Sartem 			 * When device allocation is enabled (bsmconv or TX), we
30518c2aff7Sartem 			 * set volume.ignore on all volumes, but still want
30618c2aff7Sartem 			 * Mount() to succeed when called from the euid=0
30718c2aff7Sartem 			 * device allocation program.
30818c2aff7Sartem 			 */
30918c2aff7Sartem 			if (atol (invoked_by_uid) != 0) {
31018c2aff7Sartem 				permission_denied_volume_ignore (device);
31118c2aff7Sartem 			}
31218c2aff7Sartem 		}
31318c2aff7Sartem 
31418c2aff7Sartem 		if (!libhal_volume_is_mounted (volume)) {
31518c2aff7Sartem 			not_mounted ("According to HAL, the volume is not mounted");
31618c2aff7Sartem 		}
31718c2aff7Sartem 	}
31818c2aff7Sartem 
31918c2aff7Sartem 
32018c2aff7Sartem 	/* check hal's mtab file to verify the device to unmount is actually mounted by hal */
32118c2aff7Sartem 	hal_mtab_orig = fopen ("/media/.hal-mtab", "r");
32218c2aff7Sartem 	if (hal_mtab_orig == NULL) {
32318c2aff7Sartem 		unknown_error ("Cannot open /media/.hal-mtab");
32418c2aff7Sartem 	}
32518c2aff7Sartem 	if (fseek (hal_mtab_orig, 0L, SEEK_END) != 0) {
32618c2aff7Sartem 		unknown_error ("Cannot seek to end of /media/.hal-mtab");
32718c2aff7Sartem 	}
32818c2aff7Sartem 	hal_mtab_orig_len = ftell (hal_mtab_orig);
32918c2aff7Sartem 	if (hal_mtab_orig_len < 0) {
33018c2aff7Sartem 		unknown_error ("Cannot determine size of /media/.hal-mtab");
33118c2aff7Sartem 	}
33218c2aff7Sartem 	rewind (hal_mtab_orig);
33318c2aff7Sartem 	hal_mtab_buf = g_new0 (char, hal_mtab_orig_len + 1);
33418c2aff7Sartem 	num_read = fread (hal_mtab_buf, 1, hal_mtab_orig_len, hal_mtab_orig);
33518c2aff7Sartem 	if (num_read != hal_mtab_orig_len) {
33618c2aff7Sartem 		unknown_error ("Cannot read from /media/.hal-mtab");
33718c2aff7Sartem 	}
33818c2aff7Sartem 	fclose (hal_mtab_orig);
33918c2aff7Sartem 
34018c2aff7Sartem #ifdef DEBUG
34118c2aff7Sartem 	printf ("hal_mtab = '%s'\n", hal_mtab_buf);
34218c2aff7Sartem #endif
34318c2aff7Sartem 
34418c2aff7Sartem 	lines = g_strsplit (hal_mtab_buf, "\n", 0);
34518c2aff7Sartem 	g_free (hal_mtab_buf);
34618c2aff7Sartem 
34718c2aff7Sartem 	mount_point_to_unmount = NULL;
34818c2aff7Sartem 	mounted_by_other_uid = TRUE;
34918c2aff7Sartem 
35018c2aff7Sartem 	/* find the entry we're going to unmount */
35118c2aff7Sartem 	for (i = 0; lines[i] != NULL; i++) {
35218c2aff7Sartem 		char **line_elements;
35318c2aff7Sartem 		char *special, *dosp;
35418c2aff7Sartem 		struct stat st;
35518c2aff7Sartem 
35618c2aff7Sartem #ifdef DEBUG
35718c2aff7Sartem 		printf (" line = '%s'\n", lines[i]);
35818c2aff7Sartem #endif
35918c2aff7Sartem 
36018c2aff7Sartem 		if ((lines[i])[0] == '#')
36118c2aff7Sartem 			continue;
36218c2aff7Sartem 
36318c2aff7Sartem 		line_elements = g_strsplit (lines[i], "\t", 6);
36418c2aff7Sartem 		if (g_strv_length (line_elements) == 6) {
36518c2aff7Sartem 
36618c2aff7Sartem #ifdef DEBUG
36718c2aff7Sartem 			printf ("  devfile     = '%s'\n", line_elements[0]);
36818c2aff7Sartem 			printf ("  uid         = '%s'\n", line_elements[1]);
36918c2aff7Sartem 			printf ("  session id  = '%s'\n", line_elements[2]);
37018c2aff7Sartem 			printf ("  fs          = '%s'\n", line_elements[3]);
37118c2aff7Sartem 			printf ("  options     = '%s'\n", line_elements[4]);
37218c2aff7Sartem 			printf ("  mount_point = '%s'\n", line_elements[5]);
37318c2aff7Sartem #endif
37418c2aff7Sartem 
37518c2aff7Sartem 			if (strcmp (line_elements[0], device) == 0) {
37618c2aff7Sartem 				char *line_to_free;
37718c2aff7Sartem 
37818c2aff7Sartem 				if (strcmp (line_elements[1], invoked_by_uid) == 0) {
37918c2aff7Sartem 					mounted_by_other_uid = FALSE;
38018c2aff7Sartem 				}
38118c2aff7Sartem #ifdef sun
382*7b1f4223SMilan Jurik 				if (stat("/dev/vt/console_user", &st) == 0 &&
38318c2aff7Sartem 				    st.st_uid == atoi (invoked_by_uid)) {
38418c2aff7Sartem 					/*
38518c2aff7Sartem 					 * Owner is allowed to take over. Before we have real
38618c2aff7Sartem 					 * ownership in HAL, assume it's the console owner.
38718c2aff7Sartem 					 */
38818c2aff7Sartem 					mounted_by_other_uid = FALSE;
38918c2aff7Sartem 				}
39018c2aff7Sartem #endif /* sun */
39118c2aff7Sartem 				mount_point_to_unmount = g_strdup (line_elements[5]);
39218c2aff7Sartem 
39318c2aff7Sartem 				line_to_free = lines[i];
39418c2aff7Sartem 
39518c2aff7Sartem 				for (j = i; lines[j] != NULL; j++) {
39618c2aff7Sartem 					lines[j] = lines[j+1];
39718c2aff7Sartem 				}
39818c2aff7Sartem 				lines[j] = NULL;
39918c2aff7Sartem 
40018c2aff7Sartem 				g_free (line_to_free);
40118c2aff7Sartem 
40218c2aff7Sartem 				g_strfreev (line_elements);
40318c2aff7Sartem 				goto line_found;
40418c2aff7Sartem 
40518c2aff7Sartem 			}
40618c2aff7Sartem 
40718c2aff7Sartem 		}
40818c2aff7Sartem 
40918c2aff7Sartem 		g_strfreev (line_elements);
41018c2aff7Sartem 	}
41118c2aff7Sartem line_found:
41218c2aff7Sartem 
41318c2aff7Sartem 	if (mount_point_to_unmount == NULL) {
41418c2aff7Sartem 		not_mounted_by_hal ("Device to unmount is not in /media/.hal-mtab so it is not mounted by HAL");
41518c2aff7Sartem 	}
41618c2aff7Sartem 
41718c2aff7Sartem 	/* bail out, unless if we got the "hal-storage-can-unmount-volumes-mounted-by-others" privilege only
41818c2aff7Sartem 	 * if mounted_by_other_uid==TRUE
41918c2aff7Sartem 	 *
42018c2aff7Sartem 	 * We allow uid 0 to actually ensure that Unmount(options=["lazy"], "/dev/blah") works from addon-storage.
42118c2aff7Sartem 	 */
42218c2aff7Sartem 	if ((strcmp (invoked_by_uid, "0") != 0) && mounted_by_other_uid) {
42318c2aff7Sartem 		/* TODO: actually check for privilege "hal-storage-can-unmount-volumes-mounted-by-others" */
42418c2aff7Sartem 		permission_denied_privilege ("hal-storage-can-unmount-volumes-mounted-by-others", invoked_by_uid);
42518c2aff7Sartem 	}
42618c2aff7Sartem 
42718c2aff7Sartem 	/* create new .hal-mtab~ file without the entry we're going to unmount */
42818c2aff7Sartem 	hal_mtab_new = fopen ("/media/.hal-mtab~", "w");
42918c2aff7Sartem 	if (hal_mtab_new == NULL) {
43018c2aff7Sartem 		unknown_error ("Cannot create /media/.hal-mtab~");
43118c2aff7Sartem 	}
43218c2aff7Sartem 	for (i = 0; lines[i] != NULL; i++) {
43318c2aff7Sartem 		if (i > 0) {
43418c2aff7Sartem 			char anewl[2] = "\n\0";
43518c2aff7Sartem 			if (fwrite (anewl, 1, 1, hal_mtab_new) != 1) {
43618c2aff7Sartem 				unknown_error ("Cannot write to /media/.hal-mtab~");
43718c2aff7Sartem 			}
43818c2aff7Sartem 		}
43918c2aff7Sartem 
44018c2aff7Sartem 		if (fwrite (lines[i], 1, strlen (lines[i]), hal_mtab_new) != strlen (lines[i])) {
44118c2aff7Sartem 			unknown_error ("Cannot write to /media/.hal-mtab~");
44218c2aff7Sartem 		}
44318c2aff7Sartem 
44418c2aff7Sartem 	}
44518c2aff7Sartem 	fclose (hal_mtab_new);
44618c2aff7Sartem 
44718c2aff7Sartem 	g_strfreev (lines);
44818c2aff7Sartem 
44918c2aff7Sartem 	/* construct arguments to /bin/umount */
45018c2aff7Sartem 	na = 0;
45118c2aff7Sartem 	args[na++] = UMOUNT;
45218c2aff7Sartem 	if (option_lazy)
45318c2aff7Sartem 		args[na++] = "-l";
45418c2aff7Sartem 	if (option_force)
45518c2aff7Sartem 		args[na++] = "-f";
45618c2aff7Sartem 	args[na++] = (char *) device;
45718c2aff7Sartem 	args[na++] = NULL;
45818c2aff7Sartem 
45918c2aff7Sartem #ifdef DEBUG
46018c2aff7Sartem 	printf ("will umount %s (mounted at '%s'), mounted_by_other_uid=%d\n",
46118c2aff7Sartem 		device, mount_point_to_unmount, mounted_by_other_uid);
46218c2aff7Sartem #endif
46318c2aff7Sartem 
46418c2aff7Sartem 	/* invoke /bin/umount */
46518c2aff7Sartem 	if (!g_spawn_sync ("/",
46618c2aff7Sartem 			   args,
46718c2aff7Sartem 			   NULL,
46818c2aff7Sartem 			   0,
46918c2aff7Sartem 			   NULL,
47018c2aff7Sartem 			   NULL,
47118c2aff7Sartem 			   &sout,
47218c2aff7Sartem 			   &serr,
47318c2aff7Sartem 			   &exit_status,
47418c2aff7Sartem 			   &err)) {
47518c2aff7Sartem 		printf ("Cannot execute %s\n", UMOUNT);
47618c2aff7Sartem 		unlink ("/media/.hal-mtab~");
47718c2aff7Sartem 		unknown_error ("Cannot spawn " UMOUNT);
47818c2aff7Sartem 	}
47918c2aff7Sartem 
48018c2aff7Sartem 	/* check if unmount was succesful */
48118c2aff7Sartem 	if (exit_status != 0) {
48218c2aff7Sartem 		printf ("%s error %d, stdout='%s', stderr='%s'\n", UMOUNT, exit_status, sout, serr);
48318c2aff7Sartem 
48418c2aff7Sartem 		if (strstr (serr, "device is busy") != NULL) {
48518c2aff7Sartem 			unlink ("/media/.hal-mtab~");
48618c2aff7Sartem 			device_busy (serr);
48718c2aff7Sartem 		} else {
48818c2aff7Sartem 			unlink ("/media/.hal-mtab~");
48918c2aff7Sartem 			unknown_error (serr);
49018c2aff7Sartem 		}
49118c2aff7Sartem 	}
49218c2aff7Sartem 
49318c2aff7Sartem #ifdef sun
49418c2aff7Sartem 	if ((adt_data = get_audit_export_data (system_bus,
49518c2aff7Sartem 	    invoked_by_syscon_name, &adt_data_size)) != NULL) {
49618c2aff7Sartem 		audit_volume (adt_data, ADT_detach, WEXITSTATUS(exit_status),
49718c2aff7Sartem 		    "solaris.device.mount.removable",
49818c2aff7Sartem 		    mount_point_to_unmount, device, NULL);
49918c2aff7Sartem 		free (adt_data);
50018c2aff7Sartem 	}
50118c2aff7Sartem #endif
50218c2aff7Sartem 
50318c2aff7Sartem 	/* unmount was succesful, remove directory we created in Mount() */
50418c2aff7Sartem #ifdef sun
50518c2aff7Sartem 	if (strncmp (mount_point_to_unmount, "/media/", 7) == 0)
50618c2aff7Sartem #endif
50718c2aff7Sartem 	if (g_rmdir (mount_point_to_unmount) != 0) {
50818c2aff7Sartem 		unlink ("/media/.hal-mtab~");
50918c2aff7Sartem 		unknown_error ("Cannot remove directory");
51018c2aff7Sartem 	}
51118c2aff7Sartem 
51218c2aff7Sartem 	/* set new .hal-mtab file */
51318c2aff7Sartem 	if (rename ("/media/.hal-mtab~", "/media/.hal-mtab") != 0) {
51418c2aff7Sartem 		unlink ("/media/.hal-mtab~");
51518c2aff7Sartem 		unknown_error ("Cannot rename /media/.hal-mtab~ to /media/.hal-mtab");
51618c2aff7Sartem 	}
51718c2aff7Sartem 
51818c2aff7Sartem #ifdef DEBUG
51918c2aff7Sartem 	printf ("done unmounting\n");
52018c2aff7Sartem #endif
52118c2aff7Sartem 	openlog ("hald", 0, LOG_DAEMON);
52218c2aff7Sartem 	syslog (LOG_INFO, "unmounted %s from '%s' on behalf of uid %s", device, mount_point_to_unmount, invoked_by_uid);
52318c2aff7Sartem 	closelog ();
52418c2aff7Sartem 
52518c2aff7Sartem 	g_free (sout);
52618c2aff7Sartem 	g_free (serr);
52718c2aff7Sartem 	g_free (mount_point_to_unmount);
52818c2aff7Sartem }
52918c2aff7Sartem 
53018c2aff7Sartem #define EJECT "/usr/bin/eject"
53118c2aff7Sartem 
53218c2aff7Sartem void
handle_eject(LibHalContext * hal_ctx,LibPolKitContext * pol_ctx,const char * udi,LibHalDrive * drive,const char * device,const char * invoked_by_uid,const char * invoked_by_syscon_name,gboolean closetray,DBusConnection * system_bus)53318c2aff7Sartem handle_eject (LibHalContext *hal_ctx,
53418c2aff7Sartem #ifdef HAVE_POLKIT
53518c2aff7Sartem 	      LibPolKitContext *pol_ctx,
53618c2aff7Sartem #endif
53718c2aff7Sartem 	      const char *udi,
53818c2aff7Sartem 	      LibHalDrive *drive, const char *device,
53918c2aff7Sartem 	      const char *invoked_by_uid, const char *invoked_by_syscon_name,
54018c2aff7Sartem 	      gboolean closetray, DBusConnection *system_bus)
54118c2aff7Sartem {
54218c2aff7Sartem 	GError *err = NULL;
54318c2aff7Sartem 	char *sout = NULL;
54418c2aff7Sartem 	char *serr = NULL;
54518c2aff7Sartem 	int exit_status;
54618c2aff7Sartem 	char *args[10];
54718c2aff7Sartem 	int na;
54818c2aff7Sartem #ifdef sun
54918c2aff7Sartem 	adt_export_data_t *adt_data;
55018c2aff7Sartem 	size_t adt_data_size;
55118c2aff7Sartem #endif
55218c2aff7Sartem 	/* TODO: should we require privileges here? */
55318c2aff7Sartem 
55418c2aff7Sartem #ifdef DEBUG
55518c2aff7Sartem 	printf ("device                           = %s\n", device);
55618c2aff7Sartem 	printf ("invoked by uid                   = %s\n", invoked_by_uid);
55718c2aff7Sartem 	printf ("invoked by system bus connection = %s\n", invoked_by_syscon_name);
55818c2aff7Sartem #endif
55918c2aff7Sartem 
56018c2aff7Sartem 	/* construct arguments to EJECT (e.g. /usr/bin/eject) */
56118c2aff7Sartem 	na = 0;
56218c2aff7Sartem 	args[na++] = EJECT;
56318c2aff7Sartem 	if (closetray) {
56418c2aff7Sartem 		args[na++] = "-t";
56518c2aff7Sartem 	}
56618c2aff7Sartem 	args[na++] = (char *) device;
56718c2aff7Sartem 	args[na++] = NULL;
56818c2aff7Sartem 
56918c2aff7Sartem #ifdef sun
57018c2aff7Sartem 	putenv("EJECT_DIRECT=1");
57118c2aff7Sartem #endif
57218c2aff7Sartem 
57318c2aff7Sartem #ifdef DEBUG
57418c2aff7Sartem 	printf ("will eject %s\n", device);
57518c2aff7Sartem #endif
57618c2aff7Sartem 
57718c2aff7Sartem 	/* invoke eject command */
57818c2aff7Sartem 	if (!g_spawn_sync ("/",
57918c2aff7Sartem 			   args,
58018c2aff7Sartem 			   NULL,
58118c2aff7Sartem 			   0,
58218c2aff7Sartem 			   NULL,
58318c2aff7Sartem 			   NULL,
58418c2aff7Sartem 			   &sout,
58518c2aff7Sartem 			   &serr,
58618c2aff7Sartem 			   &exit_status,
58718c2aff7Sartem 			   &err)) {
58818c2aff7Sartem 		printf ("Cannot execute %s\n", EJECT);
58918c2aff7Sartem 		unknown_error ("Cannot spawn " EJECT);
59018c2aff7Sartem 	}
59118c2aff7Sartem 
59218c2aff7Sartem #ifdef sun
59318c2aff7Sartem 	/*
59418c2aff7Sartem 	 * Solaris eject returns 4 for manually ejectable media like floppy.
59518c2aff7Sartem 	 * Consider it success.
59618c2aff7Sartem 	 */
59718c2aff7Sartem 	if (WEXITSTATUS(exit_status) == 4) {
59818c2aff7Sartem 		exit_status = 0;
59918c2aff7Sartem 	}
60018c2aff7Sartem 
60118c2aff7Sartem 	if ((adt_data = get_audit_export_data (system_bus,
60218c2aff7Sartem 	    invoked_by_syscon_name, &adt_data_size)) != NULL) {
60318c2aff7Sartem 		audit_volume (adt_data, ADT_remove, WEXITSTATUS(exit_status),
60418c2aff7Sartem 		    "solaris.device.mount.removable", NULL, device, NULL);
60518c2aff7Sartem 		free (adt_data);
60618c2aff7Sartem 	}
60718c2aff7Sartem #endif /* sun */
60818c2aff7Sartem 
60918c2aff7Sartem 	/* check if eject was succesful */
61018c2aff7Sartem 	if (exit_status != 0) {
61118c2aff7Sartem 		printf ("%s error %d, stdout='%s', stderr='%s'\n", EJECT, exit_status, sout, serr);
61218c2aff7Sartem 
61318c2aff7Sartem 		unknown_error (serr);
61418c2aff7Sartem 	}
61518c2aff7Sartem 
61618c2aff7Sartem 	/* eject was succesful... */
61718c2aff7Sartem 
61818c2aff7Sartem #ifdef DEBUG
61918c2aff7Sartem 	printf ("done ejecting\n");
62018c2aff7Sartem #endif
62118c2aff7Sartem 
62218c2aff7Sartem 	g_free (sout);
62318c2aff7Sartem 	g_free (serr);
62418c2aff7Sartem }
62518c2aff7Sartem 
62618c2aff7Sartem 
62718c2aff7Sartem static int lock_mtab_fd = -1;
62818c2aff7Sartem 
62918c2aff7Sartem gboolean
lock_hal_mtab(void)63018c2aff7Sartem lock_hal_mtab (void)
63118c2aff7Sartem {
63218c2aff7Sartem 	if (lock_mtab_fd >= 0)
63318c2aff7Sartem 		return TRUE;
63418c2aff7Sartem 
63518c2aff7Sartem 	printf ("%d: XYA attempting to get lock on /media/.hal-mtab-lock\n", getpid ());
63618c2aff7Sartem 
63718c2aff7Sartem 	lock_mtab_fd = open ("/media/.hal-mtab-lock", O_CREAT | O_RDWR);
63818c2aff7Sartem 
63918c2aff7Sartem 	if (lock_mtab_fd < 0)
64018c2aff7Sartem 		return FALSE;
64118c2aff7Sartem 
64218c2aff7Sartem tryagain:
64318c2aff7Sartem #if sun
64418c2aff7Sartem 	if (lockf (lock_mtab_fd, F_LOCK, 0) != 0) {
64518c2aff7Sartem #else
64618c2aff7Sartem 	if (flock (lock_mtab_fd, LOCK_EX) != 0) {
64718c2aff7Sartem #endif
64818c2aff7Sartem 		if (errno == EINTR)
64918c2aff7Sartem 			goto tryagain;
65018c2aff7Sartem 		return FALSE;
65118c2aff7Sartem 	}
65218c2aff7Sartem 
65318c2aff7Sartem 	printf ("%d: XYA got lock on /media/.hal-mtab-lock\n", getpid ());
65418c2aff7Sartem 
65518c2aff7Sartem 
65618c2aff7Sartem 	return TRUE;
65718c2aff7Sartem }
65818c2aff7Sartem 
65918c2aff7Sartem void
66018c2aff7Sartem unlock_hal_mtab (void)
66118c2aff7Sartem {
66218c2aff7Sartem #if sun
66318c2aff7Sartem 	lockf (lock_mtab_fd, F_ULOCK, 0);
66418c2aff7Sartem #else
66518c2aff7Sartem 	flock (lock_mtab_fd, LOCK_UN);
66618c2aff7Sartem #endif
66718c2aff7Sartem 	close (lock_mtab_fd);
66818c2aff7Sartem 	lock_mtab_fd = -1;
66918c2aff7Sartem 	printf ("%d: XYA released lock on /media/.hal-mtab-lock\n", getpid ());
67018c2aff7Sartem }
67118c2aff7Sartem 
67218c2aff7Sartem #if sun
67318c2aff7Sartem 
67418c2aff7Sartem /* map PolicyKit privilege to RBAC authorization */
67518c2aff7Sartem char *
67618c2aff7Sartem auth_from_privilege(const char *privilege)
67718c2aff7Sartem {
67818c2aff7Sartem 	char *authname;
67918c2aff7Sartem 	int i;
68018c2aff7Sartem 
68118c2aff7Sartem 	if (strcmp (privilege, "hal-storage-removable-mount") == 0) {
68218c2aff7Sartem 		authname = g_strdup ("solaris.device.mount.removable");
68318c2aff7Sartem 	} else if (strcmp (privilege, "hal-storage-removable-mount-all-options") == 0) {
68418c2aff7Sartem 		authname = g_strdup ("solaris.device.mount.alloptions.removable");
68518c2aff7Sartem 	} else if (strcmp (privilege, "hal-storage-fixed-mount") == 0) {
68618c2aff7Sartem 		authname = g_strdup ("solaris.device.mount.fixed");
68718c2aff7Sartem 	} else if (strcmp (privilege, "hal-storage-fixed-mount-all-options") == 0) {
68818c2aff7Sartem 		authname = g_strdup ("solaris.device.mount.alloptions.fixed");
68918c2aff7Sartem 	} else {
69018c2aff7Sartem 		/* replace '-' with '.' */
69118c2aff7Sartem 		authname = g_strdup (privilege);
69218c2aff7Sartem 		for (i = 0; i < strlen (authname); i++) {
69318c2aff7Sartem 			if (authname[i] == '-') {
69418c2aff7Sartem 				authname[i] = '.';
69518c2aff7Sartem 			}
69618c2aff7Sartem 		}
69718c2aff7Sartem 	}
69818c2aff7Sartem 	return (authname);
69918c2aff7Sartem }
70018c2aff7Sartem 
70118c2aff7Sartem void
70218c2aff7Sartem audit_volume(const adt_export_data_t *imported_state, au_event_t event_id,
70318c2aff7Sartem     int result, const char *auth_used, const char *mount_point,
70418c2aff7Sartem     const char *device, const char *options)
70518c2aff7Sartem {
70618c2aff7Sartem 	adt_session_data_t      *ah;
70718c2aff7Sartem 	adt_event_data_t        *event;
70818c2aff7Sartem 
70918c2aff7Sartem 	if (adt_start_session(&ah, imported_state, 0) != 0) {
71018c2aff7Sartem         	printf ("adt_start_session failed %d\n", errno);
71118c2aff7Sartem         	return;
71218c2aff7Sartem 	}
71318c2aff7Sartem 	if ((event = adt_alloc_event(ah, event_id)) == NULL) {
71418c2aff7Sartem         	printf ("adt_alloc_event(ADT_attach)\n", errno);
71518c2aff7Sartem         	return;
71618c2aff7Sartem 	}
71718c2aff7Sartem 
71818c2aff7Sartem 	switch (event_id) {
71918c2aff7Sartem 	case ADT_attach:
72018c2aff7Sartem 		event->adt_attach.auth_used = (char *)auth_used;
72118c2aff7Sartem 		event->adt_attach.mount_point = (char *)mount_point;
72218c2aff7Sartem 		event->adt_attach.device = (char *)device;
72318c2aff7Sartem 		event->adt_attach.options = (char *)options;
72418c2aff7Sartem 		break;
72518c2aff7Sartem 	case ADT_detach:
72618c2aff7Sartem 		event->adt_detach.auth_used = (char *)auth_used;
72718c2aff7Sartem 		event->adt_detach.mount_point = (char *)mount_point;
72818c2aff7Sartem 		event->adt_detach.device = (char *)device;
72918c2aff7Sartem 		event->adt_detach.options = (char *)options;
73018c2aff7Sartem 		break;
73118c2aff7Sartem 	case ADT_remove:
73218c2aff7Sartem 		event->adt_remove.auth_used = (char *)auth_used;
73318c2aff7Sartem 		event->adt_remove.mount_point = (char *)mount_point;
73418c2aff7Sartem 		event->adt_remove.device = (char *)device;
73518c2aff7Sartem 		break;
73618c2aff7Sartem 	default:
73718c2aff7Sartem 		goto out;
73818c2aff7Sartem 	}
73918c2aff7Sartem 
74018c2aff7Sartem 	if (result == 0) {
74118c2aff7Sartem 		if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
74218c2aff7Sartem 			printf ("adt_put_event(%d, success)\n", event_id);
74318c2aff7Sartem 		}
74418c2aff7Sartem 	} else {
74518c2aff7Sartem 		if (adt_put_event(event, ADT_FAILURE, result) != 0) {
74618c2aff7Sartem 			printf ("adt_put_event(%d, failure)\n", event_id);
74718c2aff7Sartem 		}
74818c2aff7Sartem 	}
74918c2aff7Sartem out:
75018c2aff7Sartem 	adt_free_event(event);
75118c2aff7Sartem 	(void) adt_end_session(ah);
75218c2aff7Sartem }
75318c2aff7Sartem 
75418c2aff7Sartem #endif /* sun */
755