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 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 * 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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