118c2aff7Sartem /*************************************************************************** 218c2aff7Sartem * CVSID: $Id$ 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 <sys/mnttab.h> 4318c2aff7Sartem #include <sys/vfstab.h> 4418c2aff7Sartem #include <sys/wait.h> 4518c2aff7Sartem #else 4618c2aff7Sartem #include <mntent.h> 4718c2aff7Sartem #endif 4818c2aff7Sartem #include <sys/types.h> 4918c2aff7Sartem #include <unistd.h> 5018c2aff7Sartem #include <errno.h> 5118c2aff7Sartem #include <syslog.h> 5218c2aff7Sartem 5318c2aff7Sartem #include <libhal.h> 5418c2aff7Sartem #include <libhal-storage.h> 5518c2aff7Sartem #ifdef HAVE_POLKIT 5618c2aff7Sartem #include <libpolkit.h> 5718c2aff7Sartem #endif 5818c2aff7Sartem 5918c2aff7Sartem #include "hal-storage-shared.h" 6018c2aff7Sartem 6118c2aff7Sartem #ifdef __FreeBSD__ 6218c2aff7Sartem #define MOUNT "/sbin/mount" 6318c2aff7Sartem #define MOUNT_OPTIONS "noexec,nosuid" 6418c2aff7Sartem #define MOUNT_TYPE_OPT "-t" 6518c2aff7Sartem #elif sun 6618c2aff7Sartem #define MOUNT "/sbin/mount" 677544909dSartem #define MOUNT_OPTIONS "nosuid" 6818c2aff7Sartem #define MOUNT_TYPE_OPT "-F" 6918c2aff7Sartem #else 7018c2aff7Sartem #define MOUNT "/bin/mount" 7118c2aff7Sartem #define MOUNT_OPTIONS "noexec,nosuid,nodev" 7218c2aff7Sartem #define MOUNT_TYPE_OPT "-t" 7318c2aff7Sartem #endif 7418c2aff7Sartem 7518c2aff7Sartem static void 7618c2aff7Sartem usage (void) 7718c2aff7Sartem { 7818c2aff7Sartem fprintf (stderr, "This program should only be started by hald.\n"); 7918c2aff7Sartem exit (1); 8018c2aff7Sartem } 8118c2aff7Sartem 8218c2aff7Sartem static void 8318c2aff7Sartem permission_denied_volume_ignore (const char *device) 8418c2aff7Sartem { 8518c2aff7Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.PermissionDenied\n"); 8618c2aff7Sartem fprintf (stderr, "Device has %s volume.ignore set to TRUE. Refusing to mount.\n", device); 8718c2aff7Sartem exit (1); 8818c2aff7Sartem } 8918c2aff7Sartem 9018c2aff7Sartem static void 9118c2aff7Sartem permission_denied_etc_fstab (const char *device) 9218c2aff7Sartem { 9318c2aff7Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.PermissionDenied\n"); 9418c2aff7Sartem fprintf (stderr, "Device %s is listed in /etc/fstab. Refusing to mount.\n", device); 9518c2aff7Sartem exit (1); 9618c2aff7Sartem } 9718c2aff7Sartem 9818c2aff7Sartem static void 9918c2aff7Sartem already_mounted (const char *device) 10018c2aff7Sartem { 10118c2aff7Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.AlreadyMounted\n"); 10218c2aff7Sartem fprintf (stderr, "Device %s is already mounted.\n", device); 10318c2aff7Sartem exit (1); 10418c2aff7Sartem } 10518c2aff7Sartem 10618c2aff7Sartem static void 10718c2aff7Sartem invalid_mount_option (const char *option, const char *uid) 10818c2aff7Sartem { 10918c2aff7Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.InvalidMountOption\n"); 11018c2aff7Sartem fprintf (stderr, "The option '%s' is not allowed for uid=%s\n", option, uid); 11118c2aff7Sartem exit (1); 11218c2aff7Sartem } 11318c2aff7Sartem 11418c2aff7Sartem static void 11518c2aff7Sartem unknown_filesystem (const char *filesystem) 11618c2aff7Sartem { 11718c2aff7Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.UnknownFilesystemType\n"); 11818c2aff7Sartem fprintf (stderr, "Unknown file system '%s'\n", filesystem); 11918c2aff7Sartem exit (1); 12018c2aff7Sartem } 12118c2aff7Sartem 12218c2aff7Sartem static void 12318c2aff7Sartem invalid_mount_point (const char *mount_point) 12418c2aff7Sartem { 12518c2aff7Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.InvalidMountpoint\n"); 12618c2aff7Sartem fprintf (stderr, "The mount point '%s' is invalid\n", mount_point); 12718c2aff7Sartem exit (1); 12818c2aff7Sartem } 12918c2aff7Sartem 13018c2aff7Sartem static void 13118c2aff7Sartem mount_point_not_available (const char *mount_point) 13218c2aff7Sartem { 13318c2aff7Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.MountPointNotAvailable\n"); 13418c2aff7Sartem fprintf (stderr, "The mount point '%s' is already occupied\n", mount_point); 13518c2aff7Sartem exit (1); 13618c2aff7Sartem } 13718c2aff7Sartem 13818c2aff7Sartem 13918c2aff7Sartem static void 14018c2aff7Sartem cannot_remount (const char *device) 14118c2aff7Sartem { 14218c2aff7Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.CannotRemount\n"); 14318c2aff7Sartem fprintf (stderr, "%s not mounted already\n", device); 14418c2aff7Sartem exit (1); 14518c2aff7Sartem } 14618c2aff7Sartem 14718c2aff7Sartem #ifdef HAVE_POLKIT 14818c2aff7Sartem static void 14918c2aff7Sartem permission_denied_privilege (const char *privilege, const char *uid) 15018c2aff7Sartem { 15118c2aff7Sartem fprintf (stderr, "org.freedesktop.Hal.Device.PermissionDeniedByPolicy\n"); 15218c2aff7Sartem fprintf (stderr, "%s refused uid %s\n", privilege, uid); 15318c2aff7Sartem exit (1); 15418c2aff7Sartem } 15518c2aff7Sartem #endif 15618c2aff7Sartem 15718c2aff7Sartem 15818c2aff7Sartem /* borrowed from gtk/gtkfilesystemunix.c in GTK+ on 02/23/2006 */ 15918c2aff7Sartem static void 16018c2aff7Sartem canonicalize_filename (gchar *filename) 16118c2aff7Sartem { 16218c2aff7Sartem gchar *p, *q; 16318c2aff7Sartem gboolean last_was_slash = FALSE; 16418c2aff7Sartem 16518c2aff7Sartem p = filename; 16618c2aff7Sartem q = filename; 16718c2aff7Sartem 16818c2aff7Sartem while (*p) 16918c2aff7Sartem { 17018c2aff7Sartem if (*p == G_DIR_SEPARATOR) 17118c2aff7Sartem { 17218c2aff7Sartem if (!last_was_slash) 17318c2aff7Sartem *q++ = G_DIR_SEPARATOR; 17418c2aff7Sartem 17518c2aff7Sartem last_was_slash = TRUE; 17618c2aff7Sartem } 17718c2aff7Sartem else 17818c2aff7Sartem { 17918c2aff7Sartem if (last_was_slash && *p == '.') 18018c2aff7Sartem { 18118c2aff7Sartem if (*(p + 1) == G_DIR_SEPARATOR || 18218c2aff7Sartem *(p + 1) == '\0') 18318c2aff7Sartem { 18418c2aff7Sartem if (*(p + 1) == '\0') 18518c2aff7Sartem break; 18618c2aff7Sartem 18718c2aff7Sartem p += 1; 18818c2aff7Sartem } 18918c2aff7Sartem else if (*(p + 1) == '.' && 19018c2aff7Sartem (*(p + 2) == G_DIR_SEPARATOR || 19118c2aff7Sartem *(p + 2) == '\0')) 19218c2aff7Sartem { 19318c2aff7Sartem if (q > filename + 1) 19418c2aff7Sartem { 19518c2aff7Sartem q--; 19618c2aff7Sartem while (q > filename + 1 && 19718c2aff7Sartem *(q - 1) != G_DIR_SEPARATOR) 19818c2aff7Sartem q--; 19918c2aff7Sartem } 20018c2aff7Sartem 20118c2aff7Sartem if (*(p + 2) == '\0') 20218c2aff7Sartem break; 20318c2aff7Sartem 20418c2aff7Sartem p += 2; 20518c2aff7Sartem } 20618c2aff7Sartem else 20718c2aff7Sartem { 20818c2aff7Sartem *q++ = *p; 20918c2aff7Sartem last_was_slash = FALSE; 21018c2aff7Sartem } 21118c2aff7Sartem } 21218c2aff7Sartem else 21318c2aff7Sartem { 21418c2aff7Sartem *q++ = *p; 21518c2aff7Sartem last_was_slash = FALSE; 21618c2aff7Sartem } 21718c2aff7Sartem } 21818c2aff7Sartem 21918c2aff7Sartem p++; 22018c2aff7Sartem } 22118c2aff7Sartem 22218c2aff7Sartem if (q > filename + 1 && *(q - 1) == G_DIR_SEPARATOR) 22318c2aff7Sartem q--; 22418c2aff7Sartem 22518c2aff7Sartem *q = '\0'; 22618c2aff7Sartem } 22718c2aff7Sartem 22818c2aff7Sartem static char * 22918c2aff7Sartem resolve_symlink (const char *file) 23018c2aff7Sartem { 23118c2aff7Sartem GError *error; 23218c2aff7Sartem char *dir; 23318c2aff7Sartem char *link; 23418c2aff7Sartem char *f; 23518c2aff7Sartem char *f1; 23618c2aff7Sartem 23718c2aff7Sartem f = g_strdup (file); 23818c2aff7Sartem 23918c2aff7Sartem while (g_file_test (f, G_FILE_TEST_IS_SYMLINK)) { 24018c2aff7Sartem link = g_file_read_link (f, &error); 24118c2aff7Sartem if (link == NULL) { 24218c2aff7Sartem g_warning ("Cannot resolve symlink %s: %s", f, error->message); 24318c2aff7Sartem g_error_free (error); 24418c2aff7Sartem g_free (f); 24518c2aff7Sartem f = NULL; 24618c2aff7Sartem goto out; 24718c2aff7Sartem } 24818c2aff7Sartem 24918c2aff7Sartem dir = g_path_get_dirname (f); 25018c2aff7Sartem f1 = g_strdup_printf ("%s/%s", dir, link); 25118c2aff7Sartem g_free (dir); 25218c2aff7Sartem g_free (link); 25318c2aff7Sartem g_free (f); 25418c2aff7Sartem f = f1; 25518c2aff7Sartem } 25618c2aff7Sartem 25718c2aff7Sartem out: 25818c2aff7Sartem if (f != NULL) 25918c2aff7Sartem canonicalize_filename (f); 26018c2aff7Sartem return f; 26118c2aff7Sartem } 26218c2aff7Sartem 26318c2aff7Sartem static LibHalVolume * 26418c2aff7Sartem volume_findby (LibHalContext *hal_ctx, const char *property, const char *value) 26518c2aff7Sartem { 26618c2aff7Sartem int i; 26718c2aff7Sartem char **hal_udis; 26818c2aff7Sartem int num_hal_udis; 26918c2aff7Sartem LibHalVolume *result = NULL; 27018c2aff7Sartem char *found_udi = NULL; 27118c2aff7Sartem DBusError error; 27218c2aff7Sartem 27318c2aff7Sartem dbus_error_init (&error); 27418c2aff7Sartem if ((hal_udis = libhal_manager_find_device_string_match (hal_ctx, property, 27518c2aff7Sartem value, &num_hal_udis, &error)) == NULL) { 27618c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 27718c2aff7Sartem goto out; 27818c2aff7Sartem } 27918c2aff7Sartem for (i = 0; i < num_hal_udis; i++) { 28018c2aff7Sartem char *udi; 28118c2aff7Sartem udi = hal_udis[i]; 28218c2aff7Sartem if (libhal_device_query_capability (hal_ctx, udi, "volume", &error)) { 28318c2aff7Sartem found_udi = strdup (udi); 28418c2aff7Sartem break; 28518c2aff7Sartem } 28618c2aff7Sartem } 28718c2aff7Sartem 28818c2aff7Sartem libhal_free_string_array (hal_udis); 28918c2aff7Sartem 29018c2aff7Sartem if (found_udi != NULL) 29118c2aff7Sartem result = libhal_volume_from_udi (hal_ctx, found_udi); 29218c2aff7Sartem 29318c2aff7Sartem free (found_udi); 29418c2aff7Sartem out: 29518c2aff7Sartem return result; 29618c2aff7Sartem } 29718c2aff7Sartem 29818c2aff7Sartem static void 29918c2aff7Sartem bailout_if_in_fstab (LibHalContext *hal_ctx, const char *device, const char *label, const char *uuid) 30018c2aff7Sartem { 30118c2aff7Sartem gpointer handle; 30218c2aff7Sartem char *entry; 30318c2aff7Sartem char *_mount_point; 30418c2aff7Sartem 30518c2aff7Sartem printf (" label '%s' uuid '%s'\n", label ? label : "" , uuid ? uuid : ""); 30618c2aff7Sartem 30718c2aff7Sartem /* check if /etc/fstab mentions this device... (with symlinks etc) */ 30818c2aff7Sartem if (! fstab_open (&handle)) { 30918c2aff7Sartem printf ("cannot open /etc/fstab\n"); 31018c2aff7Sartem unknown_error ("Cannot open /etc/fstab"); 31118c2aff7Sartem } 31218c2aff7Sartem while ((entry = fstab_next (handle, &_mount_point)) != NULL) { 31318c2aff7Sartem char *resolved; 31418c2aff7Sartem 31518c2aff7Sartem #ifdef DEBUG 31618c2aff7Sartem printf ("Looking at /etc/fstab entry '%s'\n", entry); 31718c2aff7Sartem #endif 31818c2aff7Sartem if (label != NULL && g_str_has_prefix (entry, "LABEL=")) { 31918c2aff7Sartem if (strcmp (entry + 6, label) == 0) { 32018c2aff7Sartem gboolean skip_fstab_entry; 32118c2aff7Sartem 32218c2aff7Sartem skip_fstab_entry = FALSE; 32318c2aff7Sartem 32418c2aff7Sartem /* (heck, we also do the stuff below in gnome-mount) */ 32518c2aff7Sartem 32618c2aff7Sartem /* OK, so what's if someone attaches an external disk with the label '/' and 32718c2aff7Sartem * /etc/fstab has 32818c2aff7Sartem * 32918c2aff7Sartem * LABEL=/ / ext3 defaults 1 1 33018c2aff7Sartem * 33118c2aff7Sartem * in /etc/fstab as most Red Hat systems do? Bugger, this is a very common use 33218c2aff7Sartem * case; suppose that you take the disk from your Fedora server and attaches it 33318c2aff7Sartem * to your laptop. Bingo, you now have two disks with the label '/'. One must 33418c2aff7Sartem * seriously wonder if using things like LABEL=/ for / is a good idea; just 33518c2aff7Sartem * what happens if you boot in this configuration? (answer: the initrd gets 33618c2aff7Sartem * it wrong most of the time.. sigh) 33718c2aff7Sartem * 33818c2aff7Sartem * To work around this, check if the listed entry in /etc/fstab is already mounted, 33918c2aff7Sartem * if it is, then check if it's the same device_file as the given one... 34018c2aff7Sartem */ 34118c2aff7Sartem 34218c2aff7Sartem /* see if a volume is mounted at this mount point */ 34318c2aff7Sartem if (_mount_point != NULL) { 34418c2aff7Sartem LibHalVolume *mounted_vol; 34518c2aff7Sartem 34618c2aff7Sartem mounted_vol = volume_findby (hal_ctx, "volume.mount_point", _mount_point); 34718c2aff7Sartem if (mounted_vol != NULL) { 34818c2aff7Sartem const char *mounted_vol_device_file; 34918c2aff7Sartem 35018c2aff7Sartem mounted_vol_device_file = libhal_volume_get_device_file (mounted_vol); 35118c2aff7Sartem /* no need to resolve symlinks, hal uses the canonical device file */ 35218c2aff7Sartem if (mounted_vol_device_file != NULL && 35318c2aff7Sartem strcmp (mounted_vol_device_file, device) !=0) { 35418c2aff7Sartem #ifdef DEBUG 35518c2aff7Sartem printf ("Wanting to mount %s that has label %s, but /etc/fstab says LABEL=%s is to be mounted at mount point '%s'. However %s (that also has label %s), is already mounted at said mount point. So, skipping said /etc/fstab entry.\n", 35618c2aff7Sartem device, label, label, _mount_point, mounted_vol_device_file, _mount_point); 35718c2aff7Sartem #endif 35818c2aff7Sartem skip_fstab_entry = TRUE; 35918c2aff7Sartem } 36018c2aff7Sartem libhal_volume_free (mounted_vol); 36118c2aff7Sartem } 36218c2aff7Sartem } 36318c2aff7Sartem 36418c2aff7Sartem if (!skip_fstab_entry) { 36518c2aff7Sartem printf ("%s found in /etc/fstab. Not mounting.\n", entry); 36618c2aff7Sartem permission_denied_etc_fstab (device); 36718c2aff7Sartem } 36818c2aff7Sartem } 36918c2aff7Sartem } else if (uuid != NULL && g_str_has_prefix (entry, "UUID=")) { 37018c2aff7Sartem if (strcmp (entry + 5, uuid) == 0) { 37118c2aff7Sartem printf ("%s found in /etc/fstab. Not mounting.\n", entry); 37218c2aff7Sartem permission_denied_etc_fstab (device); 37318c2aff7Sartem } 37418c2aff7Sartem } else { 37518c2aff7Sartem 37618c2aff7Sartem resolved = resolve_symlink (entry); 37718c2aff7Sartem #ifdef DEBUG 37818c2aff7Sartem printf ("/etc/fstab: device %s -> %s \n", entry, resolved); 37918c2aff7Sartem #endif 38018c2aff7Sartem if (strcmp (device, resolved) == 0) { 38118c2aff7Sartem printf ("%s (-> %s) found in /etc/fstab. Not mounting.\n", entry, resolved); 38218c2aff7Sartem permission_denied_etc_fstab (device); 38318c2aff7Sartem } 38418c2aff7Sartem 38518c2aff7Sartem g_free (resolved); 38618c2aff7Sartem } 38718c2aff7Sartem } 38818c2aff7Sartem fstab_close (handle); 38918c2aff7Sartem } 39018c2aff7Sartem 39118c2aff7Sartem static gboolean 39218c2aff7Sartem device_is_mounted (const char *device, char **mount_point) 39318c2aff7Sartem { 39418c2aff7Sartem gpointer handle; 39518c2aff7Sartem char *entry; 39618c2aff7Sartem gboolean ret; 39718c2aff7Sartem 39818c2aff7Sartem ret = FALSE; 39918c2aff7Sartem 40018c2aff7Sartem /* check if /proc/mounts mentions this device... (with symlinks etc) */ 40118c2aff7Sartem if (! mtab_open (&handle)) { 40218c2aff7Sartem printf ("cannot open mount list\n"); 40318c2aff7Sartem unknown_error ("Cannot open /etc/mtab or equivalent"); 40418c2aff7Sartem } 40518c2aff7Sartem while (((entry = mtab_next (handle, mount_point)) != NULL) && (ret == FALSE)) { 40618c2aff7Sartem char *resolved; 40718c2aff7Sartem 40818c2aff7Sartem resolved = resolve_symlink (entry); 40918c2aff7Sartem #ifdef DEBUG 41018c2aff7Sartem printf ("/proc/mounts: device %s -> %s \n", entry, resolved); 41118c2aff7Sartem #endif 41218c2aff7Sartem if (strcmp (device, resolved) == 0) { 41318c2aff7Sartem printf ("%s (-> %s) found in mount list. Not mounting.\n", entry, resolved); 41418c2aff7Sartem ret = TRUE; 41518c2aff7Sartem } 41618c2aff7Sartem 41718c2aff7Sartem g_free (resolved); 41818c2aff7Sartem } 41918c2aff7Sartem mtab_close (handle); 42018c2aff7Sartem return ret; 42118c2aff7Sartem } 42218c2aff7Sartem 42318c2aff7Sartem /* maps volume_id fs types to the appropriate -t mount option */ 42418c2aff7Sartem static const char * 42518c2aff7Sartem map_fstype (const char *fstype) 42618c2aff7Sartem { 42718c2aff7Sartem #ifdef __FreeBSD__ 42818c2aff7Sartem if (! strcmp (fstype, "iso9660")) 42918c2aff7Sartem return "cd9660"; 43018c2aff7Sartem else if (! strcmp (fstype, "ext2")) 43118c2aff7Sartem return "ext2fs"; 43218c2aff7Sartem else if (! strcmp (fstype, "vfat")) 43318c2aff7Sartem return "msdosfs"; 43418c2aff7Sartem #elif sun 43518c2aff7Sartem if (! strcmp (fstype, "iso9660")) 43618c2aff7Sartem return "hsfs"; 43718c2aff7Sartem else if (! strcmp (fstype, "vfat")) 43818c2aff7Sartem return "pcfs"; 43918c2aff7Sartem #endif 44018c2aff7Sartem 44118c2aff7Sartem return fstype; 44218c2aff7Sartem } 44318c2aff7Sartem 44418c2aff7Sartem static void 44518c2aff7Sartem handle_mount (LibHalContext *hal_ctx, 44618c2aff7Sartem #ifdef HAVE_POLKIT 44718c2aff7Sartem LibPolKitContext *pol_ctx, 44818c2aff7Sartem #endif 44918c2aff7Sartem const char *udi, 45018c2aff7Sartem LibHalVolume *volume, LibHalDrive *drive, const char *device, 45118c2aff7Sartem const char *invoked_by_uid, const char *invoked_by_syscon_name, 45218c2aff7Sartem DBusConnection *system_bus) 45318c2aff7Sartem { 45418c2aff7Sartem int i, j; 45518c2aff7Sartem DBusError error; 45618c2aff7Sartem char mount_point[256]; 45718c2aff7Sartem char mount_fstype[256]; 45818c2aff7Sartem char mount_options[1024]; 45918c2aff7Sartem char **allowed_options; 46018c2aff7Sartem char **given_options; 46118c2aff7Sartem gboolean wants_to_change_uid; 46218c2aff7Sartem char *mount_dir; 46318c2aff7Sartem GError *err = NULL; 46418c2aff7Sartem char *sout = NULL; 46518c2aff7Sartem char *serr = NULL; 46618c2aff7Sartem int exit_status; 46718c2aff7Sartem char *args[10]; 46818c2aff7Sartem int na; 46918c2aff7Sartem GString *mount_option_str; 47018c2aff7Sartem gboolean pol_is_fixed; 47118c2aff7Sartem gboolean pol_change_uid; 47218c2aff7Sartem char *privilege; 47318c2aff7Sartem gboolean is_remount; 47418c2aff7Sartem #ifdef HAVE_POLKIT 47518c2aff7Sartem gboolean allowed_by_privilege; 47618c2aff7Sartem gboolean is_temporary_privilege; 47718c2aff7Sartem #endif 47818c2aff7Sartem gboolean explicit_mount_point_given; 47918c2aff7Sartem const char *end; 48018c2aff7Sartem #ifdef __FreeBSD__ 48118c2aff7Sartem struct passwd *pw; 48218c2aff7Sartem uid_t calling_uid; 48318c2aff7Sartem gid_t calling_gid; 48418c2aff7Sartem #endif 48518c2aff7Sartem const char *label; 48618c2aff7Sartem const char *uuid; 48718c2aff7Sartem const char *model; 48818c2aff7Sartem const char *drive_type; 48918c2aff7Sartem #ifdef sun 49018c2aff7Sartem adt_export_data_t *adt_data; 49118c2aff7Sartem size_t adt_data_size; 49218c2aff7Sartem gboolean append_ro = FALSE; 49318c2aff7Sartem gboolean is_abs_path = FALSE; 49418c2aff7Sartem uid_t calling_uid; 49518c2aff7Sartem 49618c2aff7Sartem calling_uid = atol (invoked_by_uid); 49718c2aff7Sartem #endif 49818c2aff7Sartem 49918c2aff7Sartem #ifdef DEBUG 50018c2aff7Sartem printf ("device = %s\n", device); 50118c2aff7Sartem printf ("invoked by uid = %s\n", invoked_by_uid); 50218c2aff7Sartem printf ("invoked by system bus connection = %s\n", invoked_by_syscon_name); 50318c2aff7Sartem #endif 50418c2aff7Sartem 50518c2aff7Sartem if (volume != NULL) { 50618c2aff7Sartem dbus_error_init (&error); 50718c2aff7Sartem if (libhal_device_get_property_bool (hal_ctx, udi, "volume.ignore", &error) || 50818c2aff7Sartem dbus_error_is_set (&error)) { 50918c2aff7Sartem if (dbus_error_is_set (&error)) { 51018c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 51118c2aff7Sartem } 51218c2aff7Sartem /* 51318c2aff7Sartem * When device allocation is enabled (bsmconv or TX), we 51418c2aff7Sartem * set volume.ignore on all volumes, but still want 51518c2aff7Sartem * Mount() to succeed when called from the euid=0 51618c2aff7Sartem * device allocation program. 51718c2aff7Sartem */ 51818c2aff7Sartem if (atol (invoked_by_uid) != 0) { 51918c2aff7Sartem permission_denied_volume_ignore (device); 52018c2aff7Sartem } 52118c2aff7Sartem } 52218c2aff7Sartem 52318c2aff7Sartem label = libhal_volume_get_label (volume); 52418c2aff7Sartem uuid = libhal_volume_get_uuid (volume); 52518c2aff7Sartem } else { 52618c2aff7Sartem label = NULL; 52718c2aff7Sartem uuid = NULL; 52818c2aff7Sartem } 52918c2aff7Sartem 53018c2aff7Sartem bailout_if_in_fstab (hal_ctx, device, label, uuid); 53118c2aff7Sartem 53218c2aff7Sartem /* TODO: sanity check that what hal exports is correct (cf. Martin Pitt's email) */ 53318c2aff7Sartem 53418c2aff7Sartem /* read from stdin */ 53518c2aff7Sartem if (strlen (fgets (mount_point, sizeof (mount_point), stdin)) > 0) 53618c2aff7Sartem mount_point [strlen (mount_point) - 1] = '\0'; 53718c2aff7Sartem if (strlen (fgets (mount_fstype, sizeof (mount_fstype), stdin)) > 0) 53818c2aff7Sartem mount_fstype [strlen (mount_fstype) - 1] = '\0'; 53918c2aff7Sartem if (strlen (fgets (mount_options, sizeof (mount_options), stdin)) > 0) 54018c2aff7Sartem mount_options [strlen (mount_options) - 1] = '\0'; 54118c2aff7Sartem /* validate that input from stdin is UTF-8 */ 54218c2aff7Sartem if (!g_utf8_validate (mount_point, -1, &end)) 54318c2aff7Sartem unknown_error ("Error validating mount_point as UTF-8"); 54418c2aff7Sartem if (!g_utf8_validate (mount_fstype, -1, &end)) 54518c2aff7Sartem unknown_error ("Error validating mount_fstype as UTF-8"); 54618c2aff7Sartem if (!g_utf8_validate (mount_options, -1, &end)) 54718c2aff7Sartem unknown_error ("Error validating mount_options as UTF-8"); 54818c2aff7Sartem 54918c2aff7Sartem #ifdef sun 55018c2aff7Sartem if (calling_uid != 0) { 55118c2aff7Sartem #endif 55218c2aff7Sartem for (i = 0; mount_point[i] != '\0'; i++) { 55318c2aff7Sartem if (mount_point[i] == '\n' || 55418c2aff7Sartem mount_point[i] == G_DIR_SEPARATOR) { 55518c2aff7Sartem unknown_error ("mount_point cannot contain the following characters: newline, G_DIR_SEPARATOR (usually /)"); 55618c2aff7Sartem } 55718c2aff7Sartem } 55818c2aff7Sartem #ifdef sun 55918c2aff7Sartem } 56018c2aff7Sartem is_abs_path = (mount_point[0] == G_DIR_SEPARATOR); 56118c2aff7Sartem #endif 56218c2aff7Sartem 56318c2aff7Sartem #ifdef DEBUG 56418c2aff7Sartem printf ("mount_point = '%s'\n", mount_point); 56518c2aff7Sartem printf ("mount_fstype = '%s'\n", mount_fstype); 56618c2aff7Sartem printf ("mount_options = '%s'\n", mount_options); 56718c2aff7Sartem #endif 56818c2aff7Sartem 56918c2aff7Sartem /* delete any trailing whitespace options from splitting the string */ 57018c2aff7Sartem given_options = g_strsplit (mount_options, "\t", 0); 57118c2aff7Sartem for (i = g_strv_length (given_options) - 1; i >= 0; --i) { 57218c2aff7Sartem if (strlen (given_options[i]) > 0) 57318c2aff7Sartem break; 57418c2aff7Sartem given_options[i] = NULL; 57518c2aff7Sartem } 57618c2aff7Sartem 57718c2aff7Sartem #ifdef sun 57818c2aff7Sartem /* for read-only media append 'ro' option if not already */ 57918c2aff7Sartem append_ro = libhal_device_get_property_bool (hal_ctx, libhal_drive_get_udi(drive), 58018c2aff7Sartem "storage.removable.solaris.read_only", NULL); 58118c2aff7Sartem 58218c2aff7Sartem if (append_ro) { 58318c2aff7Sartem for (i = 0; i < (int) g_strv_length (given_options); i++) { 58418c2aff7Sartem if (strcmp (given_options[i], "ro") == 0) { 58518c2aff7Sartem append_ro = FALSE; 58618c2aff7Sartem } 58718c2aff7Sartem } 58818c2aff7Sartem } 58918c2aff7Sartem #endif /* sun */ 59018c2aff7Sartem 59118c2aff7Sartem /* is option 'remount' included? */ 59218c2aff7Sartem is_remount = FALSE; 59318c2aff7Sartem for (i = 0; i < (int) g_strv_length (given_options); i++) { 59418c2aff7Sartem if (strcmp (given_options[i], "remount") == 0) { 59518c2aff7Sartem is_remount = TRUE; 59618c2aff7Sartem } 59718c2aff7Sartem } 59818c2aff7Sartem 59918c2aff7Sartem mount_dir = NULL; 60018c2aff7Sartem if (is_remount) { 60118c2aff7Sartem if (volume != NULL) { 60218c2aff7Sartem if (!libhal_volume_is_mounted (volume)) { 60318c2aff7Sartem cannot_remount (device); 60418c2aff7Sartem } 60518c2aff7Sartem mount_dir = g_strdup (libhal_volume_get_mount_point (volume)); 60618c2aff7Sartem } else { 60718c2aff7Sartem if (!device_is_mounted (device, &mount_dir)) { 60818c2aff7Sartem cannot_remount (device); 60918c2aff7Sartem } 61018c2aff7Sartem } 61118c2aff7Sartem 61218c2aff7Sartem if (mount_dir == NULL) { 61318c2aff7Sartem unknown_error ("Cannot get mount_dir for remount even though volume is mounted!"); 61418c2aff7Sartem } 61518c2aff7Sartem 61618c2aff7Sartem } else { 61718c2aff7Sartem if (volume != NULL) { 61818c2aff7Sartem if (libhal_volume_is_mounted (volume)) { 61918c2aff7Sartem already_mounted (device); 62018c2aff7Sartem } 62118c2aff7Sartem } else { 62218c2aff7Sartem if (device_is_mounted (device, NULL)) { 62318c2aff7Sartem already_mounted (device); 62418c2aff7Sartem } 62518c2aff7Sartem } 62618c2aff7Sartem } 62718c2aff7Sartem 62818c2aff7Sartem if (!is_remount) { 62918c2aff7Sartem /* figure out mount point if no mount point is given... */ 63018c2aff7Sartem explicit_mount_point_given = FALSE; 63118c2aff7Sartem if (strlen (mount_point) == 0) { 63218c2aff7Sartem char *p; 63318c2aff7Sartem const char *label; 63418c2aff7Sartem 63518c2aff7Sartem if (volume != NULL) 63618c2aff7Sartem label = libhal_volume_get_label (volume); 63718c2aff7Sartem else 63818c2aff7Sartem label = NULL; 63918c2aff7Sartem 64018c2aff7Sartem model = libhal_drive_get_model (drive); 64118c2aff7Sartem drive_type = libhal_drive_get_type_textual (drive); 64218c2aff7Sartem 64318c2aff7Sartem if (label != NULL) { 64418c2aff7Sartem /* best - use label */ 64518c2aff7Sartem g_strlcpy (mount_point, label, sizeof (mount_point)); 64618c2aff7Sartem 64718c2aff7Sartem } else if ((model != NULL) && (strlen (model) > 0)) { 64818c2aff7Sartem g_strlcpy (mount_point, model, sizeof (mount_point)); 64918c2aff7Sartem } else if ((drive_type != NULL) && (strlen (drive_type) > 0)) { 65018c2aff7Sartem g_strlcpy (mount_point, drive_type, sizeof (mount_point)); 65118c2aff7Sartem } else { 65218c2aff7Sartem /* fallback - use "disk" */ 65318c2aff7Sartem g_snprintf (mount_point, sizeof (mount_point), "disk"); 65418c2aff7Sartem } 65518c2aff7Sartem 65618c2aff7Sartem /* sanitize computed mount point name, e.g. replace invalid chars with '-' */ 65718c2aff7Sartem p = mount_point; 65818c2aff7Sartem while (TRUE) { 65918c2aff7Sartem p = g_utf8_strchr (mount_point, -1, G_DIR_SEPARATOR); 66018c2aff7Sartem if (p == NULL) 66118c2aff7Sartem break; 66218c2aff7Sartem *p = '-'; 66318c2aff7Sartem }; 66418c2aff7Sartem 66518c2aff7Sartem } else { 66618c2aff7Sartem explicit_mount_point_given = TRUE; 66718c2aff7Sartem } 66818c2aff7Sartem 66918c2aff7Sartem /* check mount point name - only forbid separators */ 67018c2aff7Sartem #ifdef sun 67118c2aff7Sartem if (calling_uid != 0) { 67218c2aff7Sartem #endif 67318c2aff7Sartem if (g_utf8_strchr (mount_point, -1, G_DIR_SEPARATOR) != NULL) { 67418c2aff7Sartem printf ("'%s' is an invalid mount point\n", mount_point); 67518c2aff7Sartem invalid_mount_point (mount_point); 67618c2aff7Sartem } 67718c2aff7Sartem #ifdef sun 67818c2aff7Sartem } 67918c2aff7Sartem #endif 68018c2aff7Sartem 68118c2aff7Sartem /* check if mount point is available - append number to mount point */ 68218c2aff7Sartem i = 0; 68318c2aff7Sartem mount_dir = NULL; 68418c2aff7Sartem while (TRUE) { 68518c2aff7Sartem g_free (mount_dir); 68618c2aff7Sartem #ifdef sun 68718c2aff7Sartem if (is_abs_path) 68818c2aff7Sartem mount_dir = g_strdup (mount_point); 68918c2aff7Sartem else 69018c2aff7Sartem #endif 69118c2aff7Sartem if (i == 0) 69218c2aff7Sartem mount_dir = g_strdup_printf ("/media/%s", mount_point); 69318c2aff7Sartem else 69418c2aff7Sartem mount_dir = g_strdup_printf ("/media/%s-%d", mount_point, i); 69518c2aff7Sartem 69618c2aff7Sartem #ifdef DEBUG 69718c2aff7Sartem printf ("trying dir %s\n", mount_dir); 69818c2aff7Sartem #endif 69918c2aff7Sartem 70018c2aff7Sartem /* XXX should test for being a mount point */ 70118c2aff7Sartem if (!g_file_test (mount_dir, G_FILE_TEST_EXISTS)) { 70218c2aff7Sartem break; 70318c2aff7Sartem } 704*18c4e255SLin Guo - Sun Microsystems 70518c2aff7Sartem if (explicit_mount_point_given) { 70618c2aff7Sartem mount_point_not_available (mount_dir); 70718c2aff7Sartem } 70818c2aff7Sartem 70918c2aff7Sartem i++; 71018c2aff7Sartem } 71118c2aff7Sartem } 71218c2aff7Sartem 71318c2aff7Sartem dbus_error_init (&error); 71418c2aff7Sartem allowed_options = libhal_device_get_property_strlist (hal_ctx, udi, "volume.mount.valid_options", &error); 71518c2aff7Sartem if (dbus_error_is_set (&error)) { 71618c2aff7Sartem unknown_error ("Cannot get volume.mount.valid_options"); 71718c2aff7Sartem dbus_error_free (&error); 71818c2aff7Sartem } 71918c2aff7Sartem 72018c2aff7Sartem #ifdef DEBUG 72118c2aff7Sartem for (i = 0; given_options[i] != NULL; i++) 72218c2aff7Sartem printf ("given_options[%d] = '%s'\n", i, given_options[i]); 72318c2aff7Sartem for (i = 0; allowed_options[i] != NULL; i++) 72418c2aff7Sartem printf ("allowed_options[%d] = '%s'\n", i, allowed_options[i]); 72518c2aff7Sartem #endif 72618c2aff7Sartem 72718c2aff7Sartem wants_to_change_uid = FALSE; 72818c2aff7Sartem 72918c2aff7Sartem /* check mount options */ 73018c2aff7Sartem for (i = 0; given_options[i] != NULL; i++) { 73118c2aff7Sartem char *given = given_options[i]; 73218c2aff7Sartem 73318c2aff7Sartem for (j = 0; allowed_options[j] != NULL; j++) { 73418c2aff7Sartem char *allow = allowed_options[j]; 73518c2aff7Sartem int allow_len = strlen (allow); 73618c2aff7Sartem 73718c2aff7Sartem if (strcmp (given, allow) == 0) { 73818c2aff7Sartem goto option_ok; 73918c2aff7Sartem } 74018c2aff7Sartem 74118c2aff7Sartem if ((allow[allow_len - 1] == '=') && 74218c2aff7Sartem (strncmp (given, allow, allow_len) == 0) && 74318c2aff7Sartem (int) strlen (given) > allow_len) { 74418c2aff7Sartem 74518c2aff7Sartem /* option matched allowed ending in '=', e.g. 74618c2aff7Sartem * given == "umask=foobar" and allowed == "umask=" 74718c2aff7Sartem */ 74818c2aff7Sartem if (strcmp (allow, "uid=") == 0) { 74918c2aff7Sartem uid_t uid; 75018c2aff7Sartem char *endp; 75118c2aff7Sartem /* check for uid=, it requires special handling */ 75218c2aff7Sartem uid = (uid_t) strtol (given + allow_len, &endp, 10); 75318c2aff7Sartem if (*endp != '\0') { 75418c2aff7Sartem printf ("'%s' is not a number?\n", given); 75518c2aff7Sartem unknown_error ("option uid is malformed"); 75618c2aff7Sartem } 75718c2aff7Sartem #ifdef DEBUG 75818c2aff7Sartem printf ("%s with uid %d\n", allow, uid); 75918c2aff7Sartem #endif 76018c2aff7Sartem wants_to_change_uid = TRUE; 76118c2aff7Sartem 76218c2aff7Sartem goto option_ok; 76318c2aff7Sartem } else { 76418c2aff7Sartem 76518c2aff7Sartem goto option_ok; 76618c2aff7Sartem } 76718c2aff7Sartem } 76818c2aff7Sartem } 76918c2aff7Sartem 77018c2aff7Sartem /* apparently option was not ok */ 77118c2aff7Sartem invalid_mount_option (given, invoked_by_uid); 77218c2aff7Sartem 77318c2aff7Sartem option_ok: 77418c2aff7Sartem ; 77518c2aff7Sartem } 77618c2aff7Sartem 77718c2aff7Sartem /* Check privilege */ 77818c2aff7Sartem pol_is_fixed = TRUE; 77918c2aff7Sartem if (libhal_drive_is_hotpluggable (drive) || libhal_drive_uses_removable_media (drive)) 78018c2aff7Sartem pol_is_fixed = FALSE; 78118c2aff7Sartem 78218c2aff7Sartem pol_change_uid = FALSE; 78318c2aff7Sartem /* don't consider uid= on non-pollable drives for the purpose of policy 78418c2aff7Sartem * (since these drives normally use vfat) 78518c2aff7Sartem */ 78618c2aff7Sartem if (volume != NULL) { 78718c2aff7Sartem /* don't consider uid= on vfat, iso9660, udf change-uid for the purpose of policy 78818c2aff7Sartem * (since these doesn't contain uid/gid bits) 78918c2aff7Sartem */ 79018c2aff7Sartem if (strcmp (libhal_volume_get_fstype (volume), "vfat") != 0 && 79118c2aff7Sartem strcmp (libhal_volume_get_fstype (volume), "iso9660") != 0 && 79218c2aff7Sartem strcmp (libhal_volume_get_fstype (volume), "udf") != 0) { 79318c2aff7Sartem pol_change_uid = wants_to_change_uid; 79418c2aff7Sartem } 79518c2aff7Sartem } 79618c2aff7Sartem 79718c2aff7Sartem if (pol_is_fixed) { 79818c2aff7Sartem if (pol_change_uid) { 79918c2aff7Sartem privilege = "hal-storage-fixed-mount-all-options"; 80018c2aff7Sartem } else { 80118c2aff7Sartem privilege = "hal-storage-fixed-mount"; 80218c2aff7Sartem } 80318c2aff7Sartem } else { 80418c2aff7Sartem if (pol_change_uid) { 80518c2aff7Sartem privilege = "hal-storage-removable-mount-all-options"; 80618c2aff7Sartem } else { 80718c2aff7Sartem privilege = "hal-storage-removable-mount"; 80818c2aff7Sartem } 80918c2aff7Sartem } 81018c2aff7Sartem 81118c2aff7Sartem #ifdef DEBUG 81218c2aff7Sartem printf ("using privilege %s for uid %s, system_bus_connection %s\n", privilege, invoked_by_uid, 81318c2aff7Sartem invoked_by_syscon_name); 81418c2aff7Sartem #endif 81518c2aff7Sartem 81618c2aff7Sartem #ifdef HAVE_POLKIT 81718c2aff7Sartem if (libpolkit_is_uid_allowed_for_privilege (pol_ctx, 81818c2aff7Sartem invoked_by_syscon_name, 81918c2aff7Sartem invoked_by_uid, 82018c2aff7Sartem privilege, 82118c2aff7Sartem udi, 82218c2aff7Sartem &allowed_by_privilege, 82318c2aff7Sartem &is_temporary_privilege, 82418c2aff7Sartem NULL) != LIBPOLKIT_RESULT_OK) { 82518c2aff7Sartem printf ("cannot lookup privilege\n"); 82618c2aff7Sartem unknown_error ("Cannot lookup privilege from PolicyKit"); 82718c2aff7Sartem } 82818c2aff7Sartem 82918c2aff7Sartem if (!allowed_by_privilege) { 83018c2aff7Sartem printf ("caller don't possess privilege\n"); 83118c2aff7Sartem permission_denied_privilege (privilege, invoked_by_uid); 83218c2aff7Sartem } 83318c2aff7Sartem #endif 83418c2aff7Sartem 83518c2aff7Sartem #ifdef DEBUG 83618c2aff7Sartem printf ("passed privilege\n"); 83718c2aff7Sartem #endif 83818c2aff7Sartem 83918c2aff7Sartem if (!is_remount) { 84018c2aff7Sartem /* create directory */ 84118c2aff7Sartem #ifdef sun 842b941d3fcSartem if (!g_file_test (mount_dir, G_FILE_TEST_EXISTS) && 843b941d3fcSartem (g_mkdir (mount_dir, 0755) != 0)) { 844b941d3fcSartem #else 84518c2aff7Sartem if (g_mkdir (mount_dir, 0700) != 0) { 846b941d3fcSartem #endif 84718c2aff7Sartem printf ("Cannot create '%s'\n", mount_dir); 84818c2aff7Sartem unknown_error ("Cannot create mount directory"); 84918c2aff7Sartem } 85018c2aff7Sartem 85118c2aff7Sartem #ifdef __FreeBSD__ 85218c2aff7Sartem calling_uid = (uid_t) strtol (invoked_by_uid, (char **) NULL, 10); 85318c2aff7Sartem pw = getpwuid (calling_uid); 85418c2aff7Sartem if (pw != NULL) { 85518c2aff7Sartem calling_gid = pw->pw_gid; 85618c2aff7Sartem } else { 85718c2aff7Sartem calling_gid = 0; 85818c2aff7Sartem } 85918c2aff7Sartem if (chown (mount_dir, calling_uid, calling_gid) != 0) { 86018c2aff7Sartem printf ("Cannot chown '%s' to uid: %d, gid: %d\n", mount_dir, 86118c2aff7Sartem calling_uid, calling_gid); 86218c2aff7Sartem g_rmdir (mount_dir); 86318c2aff7Sartem unknown_error (); 86418c2aff7Sartem } 86518c2aff7Sartem #endif 86618c2aff7Sartem } 86718c2aff7Sartem 86818c2aff7Sartem char *mount_option_commasep = NULL; 86918c2aff7Sartem char *mount_do_fstype = "auto"; 87018c2aff7Sartem 87118c2aff7Sartem /* construct arguments to mount */ 87218c2aff7Sartem na = 0; 87318c2aff7Sartem args[na++] = MOUNT; 87418c2aff7Sartem if (strlen (mount_fstype) > 0) { 87518c2aff7Sartem mount_do_fstype = (char *) map_fstype (mount_fstype); 87618c2aff7Sartem } else if (volume == NULL) { 87718c2aff7Sartem /* non-pollable drive; force auto */ 87818c2aff7Sartem mount_do_fstype = "auto"; 87918c2aff7Sartem } else if (libhal_volume_get_fstype (volume) != NULL && strlen (libhal_volume_get_fstype (volume)) > 0) { 88018c2aff7Sartem mount_do_fstype = (char *) map_fstype (libhal_volume_get_fstype (volume)); 88118c2aff7Sartem } 88218c2aff7Sartem args[na++] = MOUNT_TYPE_OPT; 88318c2aff7Sartem args[na++] = mount_do_fstype; 88418c2aff7Sartem 88518c2aff7Sartem args[na++] = "-o"; 88618c2aff7Sartem mount_option_str = g_string_new (MOUNT_OPTIONS); 88718c2aff7Sartem for (i = 0; given_options[i] != NULL; i++) { 88818c2aff7Sartem g_string_append (mount_option_str, ","); 88918c2aff7Sartem g_string_append (mount_option_str, given_options[i]); 89018c2aff7Sartem } 89118c2aff7Sartem #ifdef sun 89218c2aff7Sartem if (append_ro) { 89318c2aff7Sartem g_string_append (mount_option_str, ",ro"); 89418c2aff7Sartem } 89518c2aff7Sartem #endif 89618c2aff7Sartem mount_option_commasep = g_string_free (mount_option_str, FALSE); /* leak! */ 89718c2aff7Sartem args[na++] = mount_option_commasep; 89818c2aff7Sartem args[na++] = (char *) device; 89918c2aff7Sartem args[na++] = mount_dir; 90018c2aff7Sartem args[na++] = NULL; 90118c2aff7Sartem 90218c2aff7Sartem /* TODO FIXME XXX HACK: OK, so we should rewrite the options in /media/.hal-mtab .. 90318c2aff7Sartem * but it doesn't really matter much at this point */ 90418c2aff7Sartem if (!is_remount) { 90518c2aff7Sartem FILE *hal_mtab; 90618c2aff7Sartem char *mount_dir_escaped; 90718c2aff7Sartem FILE *hal_mtab_orig; 90818c2aff7Sartem int hal_mtab_orig_len; 90918c2aff7Sartem int num_read; 91018c2aff7Sartem char *hal_mtab_buf; 91118c2aff7Sartem char *hal_mtab_buf_old; 91218c2aff7Sartem 91318c2aff7Sartem /* Maintain a list in /media/.hal-mtab with entries of the following format 91418c2aff7Sartem * 91518c2aff7Sartem * <device_file>\t<uid>\t<session-id>\t<fstype>\t<options_sep_by_comma>\t<mount point>\n 91618c2aff7Sartem * 91718c2aff7Sartem * where session-id currently is unused and thus set to 0. 91818c2aff7Sartem * 91918c2aff7Sartem * Example: 92018c2aff7Sartem * 92118c2aff7Sartem * /dev/sda2 500 0 hfsplus noexec,nosuid,nodev /media/Macintosh HD 92218c2aff7Sartem * /dev/sda4 500 0 ntfs noexec,nosuid,nodev,umask=222 /media/Windows 92318c2aff7Sartem * /dev/sdb1 500 0 vfat noexec,nosuid,nodev,shortname=winnt,uid=500 /media/davidz 92418c2aff7Sartem */ 92518c2aff7Sartem 92618c2aff7Sartem 92718c2aff7Sartem if (g_file_test ("/media/.hal-mtab", G_FILE_TEST_EXISTS)) { 92818c2aff7Sartem hal_mtab_orig = fopen ("/media/.hal-mtab", "r"); 92918c2aff7Sartem if (hal_mtab_orig == NULL) { 93018c2aff7Sartem unknown_error ("Cannot open /media/.hal-mtab"); 93118c2aff7Sartem } 93218c2aff7Sartem if (fseek (hal_mtab_orig, 0L, SEEK_END) != 0) { 93318c2aff7Sartem unknown_error ("Cannot seek to end of /media/.hal-mtab"); 93418c2aff7Sartem } 93518c2aff7Sartem hal_mtab_orig_len = ftell (hal_mtab_orig); 93618c2aff7Sartem if (hal_mtab_orig_len < 0) { 93718c2aff7Sartem unknown_error ("Cannot determine size of /media/.hal-mtab"); 93818c2aff7Sartem } 93918c2aff7Sartem rewind (hal_mtab_orig); 94018c2aff7Sartem hal_mtab_buf = g_new0 (char, hal_mtab_orig_len + 1); 94118c2aff7Sartem num_read = fread (hal_mtab_buf, 1, hal_mtab_orig_len, hal_mtab_orig); 94218c2aff7Sartem if (num_read != hal_mtab_orig_len) { 94318c2aff7Sartem unknown_error ("Cannot read from /media/.hal-mtab"); 94418c2aff7Sartem } 94518c2aff7Sartem fclose (hal_mtab_orig); 94618c2aff7Sartem } else { 94718c2aff7Sartem hal_mtab_buf = g_strdup (""); 94818c2aff7Sartem } 94918c2aff7Sartem 95018c2aff7Sartem mount_dir_escaped = g_strescape (mount_dir, NULL); 95118c2aff7Sartem #ifdef DEBUG 95218c2aff7Sartem printf ("%d: XYA creating /media/.hal-mtab~\n", getpid ()); 95318c2aff7Sartem #endif 95418c2aff7Sartem hal_mtab = fopen ("/media/.hal-mtab~", "w"); 95518c2aff7Sartem if (hal_mtab == NULL) { 95618c2aff7Sartem unknown_error ("Cannot create /media/.hal-mtab~"); 95718c2aff7Sartem } 95818c2aff7Sartem hal_mtab_buf_old = hal_mtab_buf; 95918c2aff7Sartem hal_mtab_buf = g_strdup_printf ("%s%s\t%s\t0\t%s\t%s\t%s\n", 96018c2aff7Sartem hal_mtab_buf_old, 96118c2aff7Sartem device, invoked_by_uid, mount_do_fstype, 96218c2aff7Sartem mount_option_commasep, mount_dir_escaped); 96318c2aff7Sartem g_free (hal_mtab_buf_old); 96418c2aff7Sartem if (hal_mtab_buf_old == NULL) { 96518c2aff7Sartem unknown_error ("Out of memory appending to /media/.hal-mtab~"); 96618c2aff7Sartem } 96718c2aff7Sartem if (fwrite (hal_mtab_buf, 1, strlen (hal_mtab_buf), hal_mtab) != strlen (hal_mtab_buf)) { 96818c2aff7Sartem unknown_error ("Cannot write to /media/.hal-mtab~"); 96918c2aff7Sartem } 97018c2aff7Sartem fclose (hal_mtab); 97118c2aff7Sartem g_free (hal_mtab_buf); 97218c2aff7Sartem g_free (mount_dir_escaped); 97318c2aff7Sartem #ifdef DEBUG 97418c2aff7Sartem printf ("%d: XYA closing /media/.hal-mtab~\n", getpid ()); 97518c2aff7Sartem #endif 97618c2aff7Sartem } /* !is_remount */ 97718c2aff7Sartem 97818c2aff7Sartem /* now try to mount */ 97918c2aff7Sartem if (!g_spawn_sync ("/", 98018c2aff7Sartem args, 98118c2aff7Sartem NULL, 98218c2aff7Sartem 0, 98318c2aff7Sartem NULL, 98418c2aff7Sartem NULL, 98518c2aff7Sartem &sout, 98618c2aff7Sartem &serr, 98718c2aff7Sartem &exit_status, 98818c2aff7Sartem &err)) { 98918c2aff7Sartem printf ("Cannot execute %s\n", MOUNT); 99018c2aff7Sartem g_rmdir (mount_dir); 99118c2aff7Sartem unlink ("/media/.hal-mtab~"); 99218c2aff7Sartem unknown_error ("Cannot spawn " MOUNT); 99318c2aff7Sartem } 99418c2aff7Sartem 99518c2aff7Sartem 99618c2aff7Sartem if (exit_status != 0) { 99718c2aff7Sartem char errstr[] = "mount: unknown filesystem type"; 99818c2aff7Sartem 99918c2aff7Sartem printf ("%s error %d, stdout='%s', stderr='%s'\n", MOUNT, exit_status, sout, serr); 100018c2aff7Sartem 100118c2aff7Sartem if (!is_remount) { 100218c2aff7Sartem g_rmdir (mount_dir); 100318c2aff7Sartem unlink ("/media/.hal-mtab~"); 100418c2aff7Sartem } 100518c2aff7Sartem 100618c2aff7Sartem if (strncmp (errstr, serr, sizeof (errstr) - 1) == 0) { 100718c2aff7Sartem unknown_filesystem (strlen (mount_fstype) > 0 ? 100818c2aff7Sartem mount_fstype : 100918c2aff7Sartem (volume != NULL ? libhal_volume_get_fstype (volume) : "") ); 101018c2aff7Sartem } else { 101118c2aff7Sartem int n; 101218c2aff7Sartem for (n = 0; serr[n] != '\0'; n++) { 101318c2aff7Sartem if (serr[n] == '\n') { 101418c2aff7Sartem serr[n] = ' '; 101518c2aff7Sartem } 101618c2aff7Sartem } 101718c2aff7Sartem unknown_error (serr); 101818c2aff7Sartem } 101918c2aff7Sartem } 102018c2aff7Sartem 102118c2aff7Sartem if (!is_remount) { 102218c2aff7Sartem if (rename ("/media/.hal-mtab~", "/media/.hal-mtab") != 0) { 102318c2aff7Sartem printf ("rename(2) failed, errno=%d -> '%s'\n", errno, strerror (errno)); 102418c2aff7Sartem unlink ("/media/.hal-mtab~"); 102518c2aff7Sartem #ifdef DEBUG 102618c2aff7Sartem printf ("%d: XYA failed renaming /media/.hal-mtab~ to /media/.hal-mtab\n", getpid ()); 102718c2aff7Sartem #endif 102818c2aff7Sartem unknown_error ("Cannot rename /media/.hal-mtab~ to /media/.hal-mtab"); 102918c2aff7Sartem } 103018c2aff7Sartem #ifdef DEBUG 103118c2aff7Sartem printf ("%d: XYA done renaming /media/.hal-mtab~ to /media/.hal-mtab\n", getpid ()); 103218c2aff7Sartem #endif 103318c2aff7Sartem } 103418c2aff7Sartem 103518c2aff7Sartem openlog ("hald", 0, LOG_DAEMON); 103618c2aff7Sartem if (is_remount) { 103718c2aff7Sartem syslog (LOG_INFO, "remounted %s at '%s' on behalf of uid %s", device, mount_dir, invoked_by_uid); 103818c2aff7Sartem } else { 103918c2aff7Sartem syslog (LOG_INFO, "mounted %s on behalf of uid %s", device, invoked_by_uid); 104018c2aff7Sartem } 104118c2aff7Sartem closelog (); 104218c2aff7Sartem 104318c2aff7Sartem #ifdef sun 104418c2aff7Sartem if ((adt_data = get_audit_export_data (system_bus, 104518c2aff7Sartem invoked_by_syscon_name, &adt_data_size)) != NULL) { 104618c2aff7Sartem audit_volume (adt_data, ADT_attach, 104718c2aff7Sartem WEXITSTATUS(exit_status), auth_from_privilege(privilege), 104818c2aff7Sartem mount_dir, device, mount_option_commasep); 104918c2aff7Sartem free (adt_data); 105018c2aff7Sartem } 105118c2aff7Sartem #endif 105218c2aff7Sartem 105318c2aff7Sartem g_free (sout); 105418c2aff7Sartem g_free (serr); 105518c2aff7Sartem g_free (mount_dir); 105618c2aff7Sartem libhal_free_string_array (allowed_options); 105718c2aff7Sartem g_strfreev (given_options); 105818c2aff7Sartem } 105918c2aff7Sartem 106018c2aff7Sartem 106118c2aff7Sartem int 106218c2aff7Sartem main (int argc, char *argv[]) 106318c2aff7Sartem { 106418c2aff7Sartem char *udi; 106518c2aff7Sartem char *device; 106618c2aff7Sartem LibHalVolume *volume; 106718c2aff7Sartem DBusError error; 106818c2aff7Sartem LibHalContext *hal_ctx = NULL; 106918c2aff7Sartem DBusConnection *system_bus = NULL; 107018c2aff7Sartem #ifdef HAVE_POLKIT 107118c2aff7Sartem LibPolKitContext *pol_ctx = NULL; 107218c2aff7Sartem #endif 107318c2aff7Sartem char *invoked_by_uid; 107418c2aff7Sartem char *invoked_by_syscon_name; 107518c2aff7Sartem 107618c2aff7Sartem if (!lock_hal_mtab ()) { 107718c2aff7Sartem unknown_error ("Cannot obtain lock on /media/.hal-mtab"); 107818c2aff7Sartem } 107918c2aff7Sartem 108018c2aff7Sartem device = getenv ("HAL_PROP_BLOCK_DEVICE"); 108118c2aff7Sartem if (device == NULL) 108218c2aff7Sartem usage (); 108318c2aff7Sartem 108418c2aff7Sartem udi = getenv ("HAL_PROP_INFO_UDI"); 108518c2aff7Sartem if (udi == NULL) 108618c2aff7Sartem usage (); 108718c2aff7Sartem 108818c2aff7Sartem invoked_by_uid = getenv ("HAL_METHOD_INVOKED_BY_UID"); 108918c2aff7Sartem 109018c2aff7Sartem invoked_by_syscon_name = getenv ("HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME"); 109118c2aff7Sartem 109218c2aff7Sartem dbus_error_init (&error); 109318c2aff7Sartem if ((hal_ctx = libhal_ctx_init_direct (&error)) == NULL) { 109418c2aff7Sartem printf ("Cannot connect to hald\n"); 109518c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 109618c2aff7Sartem usage (); 109718c2aff7Sartem } 109818c2aff7Sartem 109918c2aff7Sartem dbus_error_init (&error); 110018c2aff7Sartem system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error); 110118c2aff7Sartem if (system_bus == NULL) { 110218c2aff7Sartem printf ("Cannot connect to the system bus\n"); 110318c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 110418c2aff7Sartem usage (); 110518c2aff7Sartem } 110618c2aff7Sartem #ifdef HAVE_POLKIT 110718c2aff7Sartem pol_ctx = libpolkit_new_context (system_bus); 110818c2aff7Sartem if (pol_ctx == NULL) { 110918c2aff7Sartem printf ("Cannot get libpolkit context\n"); 111018c2aff7Sartem unknown_error ("Cannot get libpolkit context"); 111118c2aff7Sartem } 111218c2aff7Sartem #endif 111318c2aff7Sartem 111418c2aff7Sartem volume = libhal_volume_from_udi (hal_ctx, udi); 111518c2aff7Sartem if (volume == NULL) { 111618c2aff7Sartem LibHalDrive *drive; 111718c2aff7Sartem 111818c2aff7Sartem drive = libhal_drive_from_udi (hal_ctx, udi); 111918c2aff7Sartem if (drive == NULL) { 112018c2aff7Sartem usage (); 112118c2aff7Sartem } else { 112218c2aff7Sartem handle_mount (hal_ctx, 112318c2aff7Sartem #ifdef HAVE_POLKIT 112418c2aff7Sartem pol_ctx, 112518c2aff7Sartem #endif 112618c2aff7Sartem udi, NULL, drive, device, invoked_by_uid, 112718c2aff7Sartem invoked_by_syscon_name, system_bus); 112818c2aff7Sartem } 112918c2aff7Sartem 113018c2aff7Sartem } else { 113118c2aff7Sartem const char *drive_udi; 113218c2aff7Sartem LibHalDrive *drive; 113318c2aff7Sartem 113418c2aff7Sartem drive_udi = libhal_volume_get_storage_device_udi (volume); 113518c2aff7Sartem 113618c2aff7Sartem if (drive_udi == NULL) 113718c2aff7Sartem unknown_error ("Cannot get drive_udi from volume"); 113818c2aff7Sartem drive = libhal_drive_from_udi (hal_ctx, drive_udi); 113918c2aff7Sartem if (drive == NULL) 114018c2aff7Sartem unknown_error ("Cannot get drive from hal"); 114118c2aff7Sartem 114218c2aff7Sartem handle_mount (hal_ctx, 114318c2aff7Sartem #ifdef HAVE_POLKIT 114418c2aff7Sartem pol_ctx, 114518c2aff7Sartem #endif 114618c2aff7Sartem udi, volume, drive, device, invoked_by_uid, 114718c2aff7Sartem invoked_by_syscon_name, system_bus); 114818c2aff7Sartem 114918c2aff7Sartem } 115018c2aff7Sartem 115118c2aff7Sartem unlock_hal_mtab (); 115218c2aff7Sartem 115318c2aff7Sartem return 0; 115418c2aff7Sartem } 1155