xref: /onnv-gate/usr/src/cmd/hal/tools/hal-storage-shared.c (revision 6654:e02478f0bcde)
1*2912Sartem /***************************************************************************
2*2912Sartem  * CVSID: $Id: hal-storage-mount.c,v 1.7 2006/06/21 00:44:03 david Exp $
3*2912Sartem  *
4*2912Sartem  * hal-storage-mount.c : Mount wrapper
5*2912Sartem  *
6*2912Sartem  * Copyright (C) 2006 David Zeuthen, <david@fubar.dk>
7*2912Sartem  *
8*2912Sartem  * This program is free software; you can redistribute it and/or modify
9*2912Sartem  * it under the terms of the GNU General Public License as published by
10*2912Sartem  * the Free Software Foundation; either version 2 of the License, or
11*2912Sartem  * (at your option) any later version.
12*2912Sartem  *
13*2912Sartem  * This program is distributed in the hope that it will be useful,
14*2912Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*2912Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*2912Sartem  * GNU General Public License for more details.
17*2912Sartem  *
18*2912Sartem  * You should have received a copy of the GNU General Public License
19*2912Sartem  * along with this program; if not, write to the Free Software
20*2912Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21*2912Sartem  *
22*2912Sartem  **************************************************************************/
23*2912Sartem 
24*2912Sartem 
25*2912Sartem #ifdef HAVE_CONFIG_H
26*2912Sartem #  include <config.h>
27*2912Sartem #endif
28*2912Sartem 
29*2912Sartem #include <stdio.h>
30*2912Sartem #include <stdlib.h>
31*2912Sartem #include <string.h>
32*2912Sartem #include <glib.h>
33*2912Sartem #include <glib/gstdio.h>
34*2912Sartem #ifdef __FreeBSD__
35*2912Sartem #include <fstab.h>
36*2912Sartem #include <sys/param.h>
37*2912Sartem #include <sys/ucred.h>
38*2912Sartem #include <sys/mount.h>
39*2912Sartem #include <limits.h>
40*2912Sartem #include <pwd.h>
41*2912Sartem #elif sun
42*2912Sartem #include <fcntl.h>
43*2912Sartem #include <sys/mnttab.h>
44*2912Sartem #include <sys/vfstab.h>
45*2912Sartem #include <sys/stat.h>
46*2912Sartem #include <sys/wait.h>
47*2912Sartem #include <bsm/adt.h>
48*2912Sartem #include <bsm/adt_event.h>
49*2912Sartem #else
50*2912Sartem #include <mntent.h>
51*2912Sartem #endif
52*2912Sartem #include <sys/types.h>
53*2912Sartem #include <unistd.h>
54*2912Sartem #include <sys/file.h>
55*2912Sartem #include <errno.h>
56*2912Sartem #include <syslog.h>
57*2912Sartem 
58*2912Sartem #include "hal-storage-shared.h"
59*2912Sartem 
60*2912Sartem #ifdef __FreeBSD__
61*2912Sartem struct mtab_handle
62*2912Sartem {
63*2912Sartem   struct statfs	*mounts;
64*2912Sartem   int		n_mounts;
65*2912Sartem   int		iter;
66*2912Sartem };
67*2912Sartem #endif
68*2912Sartem 
69*2912Sartem 
70*2912Sartem gboolean
mtab_open(gpointer * handle)71*2912Sartem mtab_open (gpointer *handle)
72*2912Sartem {
73*2912Sartem #ifdef __FreeBSD__
74*2912Sartem 	struct mtab_handle *mtab;
75*2912Sartem 
76*2912Sartem 	mtab = g_new0 (struct mtab_handle, 1);
77*2912Sartem 	mtab->n_mounts = getmntinfo (&mtab->mounts, MNT_NOWAIT);
78*2912Sartem 	if (mtab->n_mounts == 0) {
79*2912Sartem 		g_free (mtab);
80*2912Sartem 		return FALSE;
81*2912Sartem 	}
82*2912Sartem 
83*2912Sartem 	*handle = mtab;
84*2912Sartem 	return TRUE;
85*2912Sartem #elif sun
86*2912Sartem 	*handle = fopen (MNTTAB, "r");
87*2912Sartem 	return *handle != NULL;
88*2912Sartem #else
89*2912Sartem 	*handle = fopen ("/proc/mounts", "r");
90*2912Sartem 	return *handle != NULL;
91*2912Sartem #endif
92*2912Sartem }
93*2912Sartem 
94*2912Sartem char *
mtab_next(gpointer handle,char ** mount_point)95*2912Sartem mtab_next (gpointer handle, char **mount_point)
96*2912Sartem {
97*2912Sartem #ifdef __FreeBSD__
98*2912Sartem 	struct mtab_handle *mtab = handle;
99*2912Sartem 
100*2912Sartem 	if (mtab->iter < mtab->n_mounts)
101*2912Sartem 		return mtab->mounts[mtab->iter++].f_mntfromname;
102*2912Sartem 	else
103*2912Sartem 		return NULL;
104*2912Sartem #error TODO: set *mount_point to g_strdup()-ed value if mount_point!=NULL
105*2912Sartem #elif sun
106*2912Sartem 	static struct mnttab mnt;
107*2912Sartem 
108*2912Sartem 	if (getmntent (handle, &mnt) == 0) {
109*2912Sartem 		if (mount_point != NULL) {
110*2912Sartem 			*mount_point = g_strdup (mnt.mnt_mountp);
111*2912Sartem 		}
112*2912Sartem 		return mnt.mnt_special;
113*2912Sartem 	} else {
114*2912Sartem 		return NULL;
115*2912Sartem 	}
116*2912Sartem #else
117*2912Sartem 	struct mntent *mnt;
118*2912Sartem 
119*2912Sartem 	mnt = getmntent (handle);
120*2912Sartem 
121*2912Sartem 	if (mnt != NULL) {
122*2912Sartem 		if (mount_point != NULL) {
123*2912Sartem 			*mount_point = g_strdup (mnt->mnt_dir);
124*2912Sartem 		}
125*2912Sartem 		return mnt->mnt_fsname;
126*2912Sartem 	} else {
127*2912Sartem 		return NULL;
128*2912Sartem 	}
129*2912Sartem #endif
130*2912Sartem }
131*2912Sartem 
132*2912Sartem void
mtab_close(gpointer handle)133*2912Sartem mtab_close (gpointer handle)
134*2912Sartem {
135*2912Sartem #ifdef __FreeBSD__
136*2912Sartem 	g_free (handle);
137*2912Sartem #else
138*2912Sartem 	fclose (handle);
139*2912Sartem #endif
140*2912Sartem }
141*2912Sartem 
142*2912Sartem 
143*2912Sartem 
144*2912Sartem gboolean
fstab_open(gpointer * handle)145*2912Sartem fstab_open (gpointer *handle)
146*2912Sartem {
147*2912Sartem #ifdef __FreeBSD__
148*2912Sartem 	return setfsent () == 1;
149*2912Sartem #elif sun
150*2912Sartem 	*handle = fopen (VFSTAB, "r");
151*2912Sartem 	return *handle != NULL;
152*2912Sartem #else
153*2912Sartem 	*handle = fopen ("/etc/fstab", "r");
154*2912Sartem 	return *handle != NULL;
155*2912Sartem #endif
156*2912Sartem }
157*2912Sartem 
158*2912Sartem char *
fstab_next(gpointer handle,char ** mount_point)159*2912Sartem fstab_next (gpointer handle, char **mount_point)
160*2912Sartem {
161*2912Sartem #ifdef __FreeBSD__
162*2912Sartem 	struct fstab *fstab;
163*2912Sartem 
164*2912Sartem 	fstab = getfsent ();
165*2912Sartem 
166*2912Sartem 	/* TODO: fill out mount_point */
167*2912Sartem 	if (mount_point != NULL && fstab != NULL) {
168*2912Sartem 		*mount_point = fstab->fs_file;
169*2912Sartem 	}
170*2912Sartem 
171*2912Sartem 	return fstab ? fstab->fs_spec : NULL;
172*2912Sartem #elif sun
173*2912Sartem 	static struct vfstab v;
174*2912Sartem 
175*2912Sartem 	return getvfsent (handle, &v) == 0 ? v.vfs_special : NULL;
176*2912Sartem #else
177*2912Sartem 	struct mntent *mnt;
178*2912Sartem 
179*2912Sartem 	mnt = getmntent (handle);
180*2912Sartem 
181*2912Sartem 	if (mount_point != NULL && mnt != NULL) {
182*2912Sartem 		*mount_point = mnt->mnt_dir;
183*2912Sartem 	}
184*2912Sartem 
185*2912Sartem 	return mnt ? mnt->mnt_fsname : NULL;
186*2912Sartem #endif
187*2912Sartem }
188*2912Sartem 
189*2912Sartem void
fstab_close(gpointer handle)190*2912Sartem fstab_close (gpointer handle)
191*2912Sartem {
192*2912Sartem #ifdef __FreeBSD__
193*2912Sartem 	endfsent ();
194*2912Sartem #else
195*2912Sartem 	fclose (handle);
196*2912Sartem #endif
197*2912Sartem }
198*2912Sartem 
199*2912Sartem #ifdef __FreeBSD__
200*2912Sartem #define UMOUNT		"/sbin/umount"
201*2912Sartem #elif sun
202*2912Sartem #define UMOUNT		"/sbin/umount"
203*2912Sartem #else
204*2912Sartem #define UMOUNT		"/bin/umount"
205*2912Sartem #endif
206*2912Sartem 
207*2912Sartem void
unknown_error(const char * detail)208*2912Sartem unknown_error (const char *detail)
209*2912Sartem {
210*2912Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.Volume.UnknownFailure\n");
211*2912Sartem 	fprintf (stderr, "%s\n", detail);
212*2912Sartem 	exit (1);
213*2912Sartem }
214*2912Sartem 
215*2912Sartem 
216*2912Sartem static void
device_busy(const char * detail)217*2912Sartem device_busy (const char *detail)
218*2912Sartem {
219*2912Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.Volume.Busy\n");
220*2912Sartem 	fprintf (stderr, "%s\n", detail);
221*2912Sartem 	exit (1);
222*2912Sartem }
223*2912Sartem 
224*2912Sartem 
225*2912Sartem static void
not_mounted(const char * detail)226*2912Sartem not_mounted (const char *detail)
227*2912Sartem {
228*2912Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.Volume.NotMounted\n");
229*2912Sartem 	fprintf (stderr, "%s\n", detail);
230*2912Sartem 	exit (1);
231*2912Sartem }
232*2912Sartem 
233*2912Sartem 
234*2912Sartem static void
not_mounted_by_hal(const char * detail)235*2912Sartem not_mounted_by_hal (const char *detail)
236*2912Sartem {
237*2912Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.Volume.NotMountedByHal\n");
238*2912Sartem 	fprintf (stderr, "%s\n", detail);
239*2912Sartem 	exit (1);
240*2912Sartem }
241*2912Sartem 
242*2912Sartem static void
permission_denied_privilege(const char * privilege,const char * uid)243*2912Sartem permission_denied_privilege (const char *privilege, const char *uid)
244*2912Sartem {
245*2912Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.PermissionDeniedByPolicy\n");
246*2912Sartem 	fprintf (stderr, "%s refused uid %s\n", privilege, uid);
247*2912Sartem 	exit (1);
248*2912Sartem }
249*2912Sartem 
250*2912Sartem static void
permission_denied_volume_ignore(const char * device)251*2912Sartem permission_denied_volume_ignore (const char *device)
252*2912Sartem {
253*2912Sartem 	fprintf (stderr, "org.freedesktop.Hal.Device.Volume.PermissionDenied\n");
254*2912Sartem 	fprintf (stderr, "Device has %s volume.ignore set to TRUE. Refusing to mount.\n", device);
255*2912Sartem 	exit (1);
256*2912Sartem }
257*2912Sartem 
258*2912Sartem 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)259*2912Sartem handle_unmount (LibHalContext *hal_ctx,
260*2912Sartem #ifdef HAVE_POLKIT
261*2912Sartem 		LibPolKitContext *pol_ctx,
262*2912Sartem #endif
263*2912Sartem 		const char *udi,
264*2912Sartem 		LibHalVolume *volume, LibHalDrive *drive, const char *device,
265*2912Sartem 		const char *invoked_by_uid, const char *invoked_by_syscon_name,
266*2912Sartem 		gboolean option_lazy, gboolean option_force,
267*2912Sartem 		DBusConnection *system_bus)
268*2912Sartem {
269*2912Sartem 	int i, j;
270*2912Sartem 	DBusError error;
271*2912Sartem 	GError *err = NULL;
272*2912Sartem 	char *sout = NULL;
273*2912Sartem 	char *serr = NULL;
274*2912Sartem 	int exit_status;
275*2912Sartem 	char *args[10];
276*2912Sartem 	int na;
277*2912Sartem 	FILE *hal_mtab_orig;
278*2912Sartem 	int hal_mtab_orig_len;
279*2912Sartem 	int num_read;
280*2912Sartem 	char *hal_mtab_buf;
281*2912Sartem 	char **lines;
282*2912Sartem 	char *mount_point_to_unmount;
283*2912Sartem 	gboolean mounted_by_other_uid;
284*2912Sartem 	FILE *hal_mtab_new;
285*2912Sartem #ifdef sun
286*2912Sartem 	adt_export_data_t *adt_data;
287*2912Sartem 	size_t adt_data_size;
288*2912Sartem #endif
289*2912Sartem 
290*2912Sartem #ifdef DEBUG
291*2912Sartem 	printf ("device                           = %s\n", device);
292*2912Sartem 	printf ("invoked by uid                   = %s\n", invoked_by_uid);
293*2912Sartem 	printf ("invoked by system bus connection = %s\n", invoked_by_syscon_name);
294*2912Sartem #endif
295*2912Sartem 
296*2912Sartem 	if (volume != NULL) {
297*2912Sartem 		dbus_error_init (&error);
298*2912Sartem 		if (libhal_device_get_property_bool (hal_ctx, udi, "volume.ignore", &error) ||
299*2912Sartem 		    dbus_error_is_set (&error)) {
300*2912Sartem 			if (dbus_error_is_set (&error)) {
301*2912Sartem 				LIBHAL_FREE_DBUS_ERROR (&error);
302*2912Sartem 			}
303*2912Sartem 			/*
304*2912Sartem 			 * When device allocation is enabled (bsmconv or TX), we
305*2912Sartem 			 * set volume.ignore on all volumes, but still want
306*2912Sartem 			 * Mount() to succeed when called from the euid=0
307*2912Sartem 			 * device allocation program.
308*2912Sartem 			 */
309*2912Sartem 			if (atol (invoked_by_uid) != 0) {
310*2912Sartem 				permission_denied_volume_ignore (device);
311*2912Sartem 			}
312*2912Sartem 		}
313*2912Sartem 
314*2912Sartem 		if (!libhal_volume_is_mounted (volume)) {
315*2912Sartem 			not_mounted ("According to HAL, the volume is not mounted");
316*2912Sartem 		}
317*2912Sartem 	}
318*2912Sartem 
319*2912Sartem 
320*2912Sartem 	/* check hal's mtab file to verify the device to unmount is actually mounted by hal */
321*2912Sartem 	hal_mtab_orig = fopen ("/media/.hal-mtab", "r");
322*2912Sartem 	if (hal_mtab_orig == NULL) {
323*2912Sartem 		unknown_error ("Cannot open /media/.hal-mtab");
324*2912Sartem 	}
325*2912Sartem 	if (fseek (hal_mtab_orig, 0L, SEEK_END) != 0) {
326*2912Sartem 		unknown_error ("Cannot seek to end of /media/.hal-mtab");
327*2912Sartem 	}
328*2912Sartem 	hal_mtab_orig_len = ftell (hal_mtab_orig);
329*2912Sartem 	if (hal_mtab_orig_len < 0) {
330*2912Sartem 		unknown_error ("Cannot determine size of /media/.hal-mtab");
331*2912Sartem 	}
332*2912Sartem 	rewind (hal_mtab_orig);
333*2912Sartem 	hal_mtab_buf = g_new0 (char, hal_mtab_orig_len + 1);
334*2912Sartem 	num_read = fread (hal_mtab_buf, 1, hal_mtab_orig_len, hal_mtab_orig);
335*2912Sartem 	if (num_read != hal_mtab_orig_len) {
336*2912Sartem 		unknown_error ("Cannot read from /media/.hal-mtab");
337*2912Sartem 	}
338*2912Sartem 	fclose (hal_mtab_orig);
339*2912Sartem 
340*2912Sartem #ifdef DEBUG
341*2912Sartem 	printf ("hal_mtab = '%s'\n", hal_mtab_buf);
342*2912Sartem #endif
343*2912Sartem 
344*2912Sartem 	lines = g_strsplit (hal_mtab_buf, "\n", 0);
345*2912Sartem 	g_free (hal_mtab_buf);
346*2912Sartem 
347*2912Sartem 	mount_point_to_unmount = NULL;
348*2912Sartem 	mounted_by_other_uid = TRUE;
349*2912Sartem 
350*2912Sartem 	/* find the entry we're going to unmount */
351*2912Sartem 	for (i = 0; lines[i] != NULL; i++) {
352*2912Sartem 		char **line_elements;
353*2912Sartem 		char *special, *dosp;
354*2912Sartem 		struct stat st;
355*2912Sartem 
356*2912Sartem #ifdef DEBUG
357*2912Sartem 		printf (" line = '%s'\n", lines[i]);
358*2912Sartem #endif
359*2912Sartem 
360*2912Sartem 		if ((lines[i])[0] == '#')
361*2912Sartem 			continue;
362*2912Sartem 
363*2912Sartem 		line_elements = g_strsplit (lines[i], "\t", 6);
364*2912Sartem 		if (g_strv_length (line_elements) == 6) {
365*2912Sartem 
366*2912Sartem #ifdef DEBUG
367*2912Sartem 			printf ("  devfile     = '%s'\n", line_elements[0]);
368*2912Sartem 			printf ("  uid         = '%s'\n", line_elements[1]);
369*2912Sartem 			printf ("  session id  = '%s'\n", line_elements[2]);
370*2912Sartem 			printf ("  fs          = '%s'\n", line_elements[3]);
371*2912Sartem 			printf ("  options     = '%s'\n", line_elements[4]);
372*2912Sartem 			printf ("  mount_point = '%s'\n", line_elements[5]);
373*2912Sartem #endif
374*2912Sartem 
375*2912Sartem 			if (strcmp (line_elements[0], device) == 0) {
376*2912Sartem 				char *line_to_free;
377*2912Sartem 
378*2912Sartem 				if (strcmp (line_elements[1], invoked_by_uid) == 0) {
379*2912Sartem 					mounted_by_other_uid = FALSE;
380*2912Sartem 				}
381*2912Sartem #ifdef sun
382*2912Sartem 				if (stat("/dev/console", &st) == 0 &&
383*2912Sartem 				    st.st_uid == atoi (invoked_by_uid)) {
384*2912Sartem 					/*
385*2912Sartem 					 * Owner is allowed to take over. Before we have real
386*2912Sartem 					 * ownership in HAL, assume it's the console owner.
387*2912Sartem 					 */
388*2912Sartem 					mounted_by_other_uid = FALSE;
389*2912Sartem 				}
390*2912Sartem #endif /* sun */
391*2912Sartem 				mount_point_to_unmount = g_strdup (line_elements[5]);
392*2912Sartem 
393*2912Sartem 				line_to_free = lines[i];
394*2912Sartem 
395*2912Sartem 				for (j = i; lines[j] != NULL; j++) {
396*2912Sartem 					lines[j] = lines[j+1];
397*2912Sartem 				}
398*2912Sartem 				lines[j] = NULL;
399*2912Sartem 
400*2912Sartem 				g_free (line_to_free);
401*2912Sartem 
402*2912Sartem 				g_strfreev (line_elements);
403*2912Sartem 				goto line_found;
404*2912Sartem 
405*2912Sartem 			}
406*2912Sartem 
407*2912Sartem 		}
408*2912Sartem 
409*2912Sartem 		g_strfreev (line_elements);
410*2912Sartem 	}
411*2912Sartem line_found:
412*2912Sartem 
413*2912Sartem 	if (mount_point_to_unmount == NULL) {
414*2912Sartem 		not_mounted_by_hal ("Device to unmount is not in /media/.hal-mtab so it is not mounted by HAL");
415*2912Sartem 	}
416*2912Sartem 
417*2912Sartem 	/* bail out, unless if we got the "hal-storage-can-unmount-volumes-mounted-by-others" privilege only
418*2912Sartem 	 * if mounted_by_other_uid==TRUE
419*2912Sartem 	 *
420*2912Sartem 	 * We allow uid 0 to actually ensure that Unmount(options=["lazy"], "/dev/blah") works from addon-storage.
421*2912Sartem 	 */
422*2912Sartem 	if ((strcmp (invoked_by_uid, "0") != 0) && mounted_by_other_uid) {
423*2912Sartem 		/* TODO: actually check for privilege "hal-storage-can-unmount-volumes-mounted-by-others" */
424*2912Sartem 		permission_denied_privilege ("hal-storage-can-unmount-volumes-mounted-by-others", invoked_by_uid);
425*2912Sartem 	}
426*2912Sartem 
427*2912Sartem 	/* create new .hal-mtab~ file without the entry we're going to unmount */
428*2912Sartem 	hal_mtab_new = fopen ("/media/.hal-mtab~", "w");
429*2912Sartem 	if (hal_mtab_new == NULL) {
430*2912Sartem 		unknown_error ("Cannot create /media/.hal-mtab~");
431*2912Sartem 	}
432*2912Sartem 	for (i = 0; lines[i] != NULL; i++) {
433*2912Sartem 		if (i > 0) {
434*2912Sartem 			char anewl[2] = "\n\0";
435*2912Sartem 			if (fwrite (anewl, 1, 1, hal_mtab_new) != 1) {
436*2912Sartem 				unknown_error ("Cannot write to /media/.hal-mtab~");
437*2912Sartem 			}
438*2912Sartem 		}
439*2912Sartem 
440*2912Sartem 		if (fwrite (lines[i], 1, strlen (lines[i]), hal_mtab_new) != strlen (lines[i])) {
441*2912Sartem 			unknown_error ("Cannot write to /media/.hal-mtab~");
442*2912Sartem 		}
443*2912Sartem 
444*2912Sartem 	}
445*2912Sartem 	fclose (hal_mtab_new);
446*2912Sartem 
447*2912Sartem 	g_strfreev (lines);
448*2912Sartem 
449*2912Sartem 	/* construct arguments to /bin/umount */
450*2912Sartem 	na = 0;
451*2912Sartem 	args[na++] = UMOUNT;
452*2912Sartem 	if (option_lazy)
453*2912Sartem 		args[na++] = "-l";
454*2912Sartem 	if (option_force)
455*2912Sartem 		args[na++] = "-f";
456*2912Sartem 	args[na++] = (char *) device;
457*2912Sartem 	args[na++] = NULL;
458*2912Sartem 
459*2912Sartem #ifdef DEBUG
460*2912Sartem 	printf ("will umount %s (mounted at '%s'), mounted_by_other_uid=%d\n",
461*2912Sartem 		device, mount_point_to_unmount, mounted_by_other_uid);
462*2912Sartem #endif
463*2912Sartem 
464*2912Sartem 	/* invoke /bin/umount */
465*2912Sartem 	if (!g_spawn_sync ("/",
466*2912Sartem 			   args,
467*2912Sartem 			   NULL,
468*2912Sartem 			   0,
469*2912Sartem 			   NULL,
470*2912Sartem 			   NULL,
471*2912Sartem 			   &sout,
472*2912Sartem 			   &serr,
473*2912Sartem 			   &exit_status,
474*2912Sartem 			   &err)) {
475*2912Sartem 		printf ("Cannot execute %s\n", UMOUNT);
476*2912Sartem 		unlink ("/media/.hal-mtab~");
477*2912Sartem 		unknown_error ("Cannot spawn " UMOUNT);
478*2912Sartem 	}
479*2912Sartem 
480*2912Sartem 	/* check if unmount was succesful */
481*2912Sartem 	if (exit_status != 0) {
482*2912Sartem 		printf ("%s error %d, stdout='%s', stderr='%s'\n", UMOUNT, exit_status, sout, serr);
483*2912Sartem 
484*2912Sartem 		if (strstr (serr, "device is busy") != NULL) {
485*2912Sartem 			unlink ("/media/.hal-mtab~");
486*2912Sartem 			device_busy (serr);
487*2912Sartem 		} else {
488*2912Sartem 			unlink ("/media/.hal-mtab~");
489*2912Sartem 			unknown_error (serr);
490*2912Sartem 		}
491*2912Sartem 	}
492*2912Sartem 
493*2912Sartem #ifdef sun
494*2912Sartem 	if ((adt_data = get_audit_export_data (system_bus,
495*2912Sartem 	    invoked_by_syscon_name, &adt_data_size)) != NULL) {
496*2912Sartem 		audit_volume (adt_data, ADT_detach, WEXITSTATUS(exit_status),
497*2912Sartem 		    "solaris.device.mount.removable",
498*2912Sartem 		    mount_point_to_unmount, device, NULL);
499*2912Sartem 		free (adt_data);
500*2912Sartem 	}
501*2912Sartem #endif
502*2912Sartem 
503*2912Sartem 	/* unmount was succesful, remove directory we created in Mount() */
504*2912Sartem #ifdef sun
505*2912Sartem 	if (strncmp (mount_point_to_unmount, "/media/", 7) == 0)
506*2912Sartem #endif
507*2912Sartem 	if (g_rmdir (mount_point_to_unmount) != 0) {
508*2912Sartem 		unlink ("/media/.hal-mtab~");
509*2912Sartem 		unknown_error ("Cannot remove directory");
510*2912Sartem 	}
511*2912Sartem 
512*2912Sartem 	/* set new .hal-mtab file */
513*2912Sartem 	if (rename ("/media/.hal-mtab~", "/media/.hal-mtab") != 0) {
514*2912Sartem 		unlink ("/media/.hal-mtab~");
515*2912Sartem 		unknown_error ("Cannot rename /media/.hal-mtab~ to /media/.hal-mtab");
516*2912Sartem 	}
517*2912Sartem 
518*2912Sartem #ifdef DEBUG
519*2912Sartem 	printf ("done unmounting\n");
520*2912Sartem #endif
521*2912Sartem 	openlog ("hald", 0, LOG_DAEMON);
522*2912Sartem 	syslog (LOG_INFO, "unmounted %s from '%s' on behalf of uid %s", device, mount_point_to_unmount, invoked_by_uid);
523*2912Sartem 	closelog ();
524*2912Sartem 
525*2912Sartem 	g_free (sout);
526*2912Sartem 	g_free (serr);
527*2912Sartem 	g_free (mount_point_to_unmount);
528*2912Sartem }
529*2912Sartem 
530*2912Sartem #define EJECT "/usr/bin/eject"
531*2912Sartem 
532*2912Sartem 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)533*2912Sartem handle_eject (LibHalContext *hal_ctx,
534*2912Sartem #ifdef HAVE_POLKIT
535*2912Sartem 	      LibPolKitContext *pol_ctx,
536*2912Sartem #endif
537*2912Sartem 	      const char *udi,
538*2912Sartem 	      LibHalDrive *drive, const char *device,
539*2912Sartem 	      const char *invoked_by_uid, const char *invoked_by_syscon_name,
540*2912Sartem 	      gboolean closetray, DBusConnection *system_bus)
541*2912Sartem {
542*2912Sartem 	GError *err = NULL;
543*2912Sartem 	char *sout = NULL;
544*2912Sartem 	char *serr = NULL;
545*2912Sartem 	int exit_status;
546*2912Sartem 	char *args[10];
547*2912Sartem 	int na;
548*2912Sartem #ifdef sun
549*2912Sartem 	adt_export_data_t *adt_data;
550*2912Sartem 	size_t adt_data_size;
551*2912Sartem #endif
552*2912Sartem 	/* TODO: should we require privileges here? */
553*2912Sartem 
554*2912Sartem #ifdef DEBUG
555*2912Sartem 	printf ("device                           = %s\n", device);
556*2912Sartem 	printf ("invoked by uid                   = %s\n", invoked_by_uid);
557*2912Sartem 	printf ("invoked by system bus connection = %s\n", invoked_by_syscon_name);
558*2912Sartem #endif
559*2912Sartem 
560*2912Sartem 	/* construct arguments to EJECT (e.g. /usr/bin/eject) */
561*2912Sartem 	na = 0;
562*2912Sartem 	args[na++] = EJECT;
563*2912Sartem 	if (closetray) {
564*2912Sartem 		args[na++] = "-t";
565*2912Sartem 	}
566*2912Sartem 	args[na++] = (char *) device;
567*2912Sartem 	args[na++] = NULL;
568*2912Sartem 
569*2912Sartem #ifdef sun
570*2912Sartem 	putenv("EJECT_DIRECT=1");
571*2912Sartem #endif
572*2912Sartem 
573*2912Sartem #ifdef DEBUG
574*2912Sartem 	printf ("will eject %s\n", device);
575*2912Sartem #endif
576*2912Sartem 
577*2912Sartem 	/* invoke eject command */
578*2912Sartem 	if (!g_spawn_sync ("/",
579*2912Sartem 			   args,
580*2912Sartem 			   NULL,
581*2912Sartem 			   0,
582*2912Sartem 			   NULL,
583*2912Sartem 			   NULL,
584*2912Sartem 			   &sout,
585*2912Sartem 			   &serr,
586*2912Sartem 			   &exit_status,
587*2912Sartem 			   &err)) {
588*2912Sartem 		printf ("Cannot execute %s\n", EJECT);
589*2912Sartem 		unknown_error ("Cannot spawn " EJECT);
590*2912Sartem 	}
591*2912Sartem 
592*2912Sartem #ifdef sun
593*2912Sartem 	/*
594*2912Sartem 	 * Solaris eject returns 4 for manually ejectable media like floppy.
595*2912Sartem 	 * Consider it success.
596*2912Sartem 	 */
597*2912Sartem 	if (WEXITSTATUS(exit_status) == 4) {
598*2912Sartem 		exit_status = 0;
599*2912Sartem 	}
600*2912Sartem 
601*2912Sartem 	if ((adt_data = get_audit_export_data (system_bus,
602*2912Sartem 	    invoked_by_syscon_name, &adt_data_size)) != NULL) {
603*2912Sartem 		audit_volume (adt_data, ADT_remove, WEXITSTATUS(exit_status),
604*2912Sartem 		    "solaris.device.mount.removable", NULL, device, NULL);
605*2912Sartem 		free (adt_data);
606*2912Sartem 	}
607*2912Sartem #endif /* sun */
608*2912Sartem 
609*2912Sartem 	/* check if eject was succesful */
610*2912Sartem 	if (exit_status != 0) {
611*2912Sartem 		printf ("%s error %d, stdout='%s', stderr='%s'\n", EJECT, exit_status, sout, serr);
612*2912Sartem 
613*2912Sartem 		unknown_error (serr);
614*2912Sartem 	}
615*2912Sartem 
616*2912Sartem 	/* eject was succesful... */
617*2912Sartem 
618*2912Sartem #ifdef DEBUG
619*2912Sartem 	printf ("done ejecting\n");
620*2912Sartem #endif
621*2912Sartem 
622*2912Sartem 	g_free (sout);
623*2912Sartem 	g_free (serr);
624*2912Sartem }
625*2912Sartem 
626*2912Sartem 
627*2912Sartem static int lock_mtab_fd = -1;
628*2912Sartem 
629*2912Sartem gboolean
lock_hal_mtab(void)630*2912Sartem lock_hal_mtab (void)
631*2912Sartem {
632*2912Sartem 	if (lock_mtab_fd >= 0)
633*2912Sartem 		return TRUE;
634*2912Sartem 
635*2912Sartem 	printf ("%d: XYA attempting to get lock on /media/.hal-mtab-lock\n", getpid ());
636*2912Sartem 
637*2912Sartem 	lock_mtab_fd = open ("/media/.hal-mtab-lock", O_CREAT | O_RDWR);
638*2912Sartem 
639*2912Sartem 	if (lock_mtab_fd < 0)
640*2912Sartem 		return FALSE;
641*2912Sartem 
642*2912Sartem tryagain:
643*2912Sartem #if sun
644*2912Sartem 	if (lockf (lock_mtab_fd, F_LOCK, 0) != 0) {
645*2912Sartem #else
646*2912Sartem 	if (flock (lock_mtab_fd, LOCK_EX) != 0) {
647*2912Sartem #endif
648*2912Sartem 		if (errno == EINTR)
649*2912Sartem 			goto tryagain;
650*2912Sartem 		return FALSE;
651*2912Sartem 	}
652*2912Sartem 
653*2912Sartem 	printf ("%d: XYA got lock on /media/.hal-mtab-lock\n", getpid ());
654*2912Sartem 
655*2912Sartem 
656*2912Sartem 	return TRUE;
657*2912Sartem }
658*2912Sartem 
659*2912Sartem void
660*2912Sartem unlock_hal_mtab (void)
661*2912Sartem {
662*2912Sartem #if sun
663*2912Sartem 	lockf (lock_mtab_fd, F_ULOCK, 0);
664*2912Sartem #else
665*2912Sartem 	flock (lock_mtab_fd, LOCK_UN);
666*2912Sartem #endif
667*2912Sartem 	close (lock_mtab_fd);
668*2912Sartem 	lock_mtab_fd = -1;
669*2912Sartem 	printf ("%d: XYA released lock on /media/.hal-mtab-lock\n", getpid ());
670*2912Sartem }
671*2912Sartem 
672*2912Sartem #if sun
673*2912Sartem 
674*2912Sartem /* map PolicyKit privilege to RBAC authorization */
675*2912Sartem char *
676*2912Sartem auth_from_privilege(const char *privilege)
677*2912Sartem {
678*2912Sartem 	char *authname;
679*2912Sartem 	int i;
680*2912Sartem 
681*2912Sartem 	if (strcmp (privilege, "hal-storage-removable-mount") == 0) {
682*2912Sartem 		authname = g_strdup ("solaris.device.mount.removable");
683*2912Sartem 	} else if (strcmp (privilege, "hal-storage-removable-mount-all-options") == 0) {
684*2912Sartem 		authname = g_strdup ("solaris.device.mount.alloptions.removable");
685*2912Sartem 	} else if (strcmp (privilege, "hal-storage-fixed-mount") == 0) {
686*2912Sartem 		authname = g_strdup ("solaris.device.mount.fixed");
687*2912Sartem 	} else if (strcmp (privilege, "hal-storage-fixed-mount-all-options") == 0) {
688*2912Sartem 		authname = g_strdup ("solaris.device.mount.alloptions.fixed");
689*2912Sartem 	} else {
690*2912Sartem 		/* replace '-' with '.' */
691*2912Sartem 		authname = g_strdup (privilege);
692*2912Sartem 		for (i = 0; i < strlen (authname); i++) {
693*2912Sartem 			if (authname[i] == '-') {
694*2912Sartem 				authname[i] = '.';
695*2912Sartem 			}
696*2912Sartem 		}
697*2912Sartem 	}
698*2912Sartem 	return (authname);
699*2912Sartem }
700*2912Sartem 
701*2912Sartem void
702*2912Sartem audit_volume(const adt_export_data_t *imported_state, au_event_t event_id,
703*2912Sartem     int result, const char *auth_used, const char *mount_point,
704*2912Sartem     const char *device, const char *options)
705*2912Sartem {
706*2912Sartem 	adt_session_data_t      *ah;
707*2912Sartem 	adt_event_data_t        *event;
708*2912Sartem 
709*2912Sartem 	if (adt_start_session(&ah, imported_state, 0) != 0) {
710*2912Sartem         	printf ("adt_start_session failed %d\n", errno);
711*2912Sartem         	return;
712*2912Sartem 	}
713*2912Sartem 	if ((event = adt_alloc_event(ah, event_id)) == NULL) {
714*2912Sartem         	printf ("adt_alloc_event(ADT_attach)\n", errno);
715*2912Sartem         	return;
716*2912Sartem 	}
717*2912Sartem 
718*2912Sartem 	switch (event_id) {
719*2912Sartem 	case ADT_attach:
720*2912Sartem 		event->adt_attach.auth_used = (char *)auth_used;
721*2912Sartem 		event->adt_attach.mount_point = (char *)mount_point;
722*2912Sartem 		event->adt_attach.device = (char *)device;
723*2912Sartem 		event->adt_attach.options = (char *)options;
724*2912Sartem 		break;
725*2912Sartem 	case ADT_detach:
726*2912Sartem 		event->adt_detach.auth_used = (char *)auth_used;
727*2912Sartem 		event->adt_detach.mount_point = (char *)mount_point;
728*2912Sartem 		event->adt_detach.device = (char *)device;
729*2912Sartem 		event->adt_detach.options = (char *)options;
730*2912Sartem 		break;
731*2912Sartem 	case ADT_remove:
732*2912Sartem 		event->adt_remove.auth_used = (char *)auth_used;
733*2912Sartem 		event->adt_remove.mount_point = (char *)mount_point;
734*2912Sartem 		event->adt_remove.device = (char *)device;
735*2912Sartem 		break;
736*2912Sartem 	default:
737*2912Sartem 		goto out;
738*2912Sartem 	}
739*2912Sartem 
740*2912Sartem 	if (result == 0) {
741*2912Sartem 		if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
742*2912Sartem 			printf ("adt_put_event(%d, success)\n", event_id);
743*2912Sartem 		}
744*2912Sartem 	} else {
745*2912Sartem 		if (adt_put_event(event, ADT_FAILURE, result) != 0) {
746*2912Sartem 			printf ("adt_put_event(%d, failure)\n", event_id);
747*2912Sartem 		}
748*2912Sartem 	}
749*2912Sartem out:
750*2912Sartem 	adt_free_event(event);
751*2912Sartem 	(void) adt_end_session(ah);
752*2912Sartem }
753*2912Sartem 
754*2912Sartem #endif /* sun */
755