1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
3
* Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
#include <glib/gi18n-lib.h>
24
#include <sys/types.h>
31
#include <sys/types.h>
35
#include <glib/gstdio.h>
37
#include "udiskslogging.h"
38
#include "udiskslinuxfilesystem.h"
39
#include "udiskslinuxblockobject.h"
40
#include "udiskslinuxfsinfo.h"
41
#include "udisksdaemon.h"
42
#include "udisksstate.h"
43
#include "udisksdaemonutil.h"
44
#include "udisksmountmonitor.h"
45
#include "udisksmount.h"
46
#include "udiskslinuxdevice.h"
49
* SECTION:udiskslinuxfilesystem
50
* @title: UDisksLinuxFilesystem
51
* @short_description: Linux implementation of #UDisksFilesystem
53
* This type provides an implementation of the #UDisksFilesystem
57
typedef struct _UDisksLinuxFilesystemClass UDisksLinuxFilesystemClass;
60
* UDisksLinuxFilesystem:
62
* The #UDisksLinuxFilesystem structure contains only private data and should
63
* only be accessed using the provided API.
65
struct _UDisksLinuxFilesystem
67
UDisksFilesystemSkeleton parent_instance;
71
struct _UDisksLinuxFilesystemClass
73
UDisksFilesystemSkeletonClass parent_class;
76
static void filesystem_iface_init (UDisksFilesystemIface *iface);
78
G_DEFINE_TYPE_WITH_CODE (UDisksLinuxFilesystem, udisks_linux_filesystem, UDISKS_TYPE_FILESYSTEM_SKELETON,
79
G_IMPLEMENT_INTERFACE (UDISKS_TYPE_FILESYSTEM, filesystem_iface_init));
81
/* ---------------------------------------------------------------------------------------------------- */
84
udisks_linux_filesystem_finalize (GObject *object)
86
UDisksLinuxFilesystem *filesystem = UDISKS_LINUX_FILESYSTEM (object);
88
g_mutex_clear (&(filesystem->lock));
90
if (G_OBJECT_CLASS (udisks_linux_filesystem_parent_class)->finalize != NULL)
91
G_OBJECT_CLASS (udisks_linux_filesystem_parent_class)->finalize (object);
95
udisks_linux_filesystem_init (UDisksLinuxFilesystem *filesystem)
97
g_mutex_init (&filesystem->lock);
98
g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (filesystem),
99
G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
103
udisks_linux_filesystem_class_init (UDisksLinuxFilesystemClass *klass)
105
GObjectClass *gobject_class;
107
gobject_class = G_OBJECT_CLASS (klass);
108
gobject_class->finalize = udisks_linux_filesystem_finalize;
112
* udisks_linux_filesystem_new:
114
* Creates a new #UDisksLinuxFilesystem instance.
116
* Returns: A new #UDisksLinuxFilesystem. Free with g_object_unref().
119
udisks_linux_filesystem_new (void)
121
return UDISKS_FILESYSTEM (g_object_new (UDISKS_TYPE_LINUX_FILESYSTEM,
125
/* ---------------------------------------------------------------------------------------------------- */
128
* udisks_linux_filesystem_update:
129
* @filesystem: A #UDisksLinuxFilesystem.
130
* @object: The enclosing #UDisksLinuxBlockObject instance.
132
* Updates the interface.
135
udisks_linux_filesystem_update (UDisksLinuxFilesystem *filesystem,
136
UDisksLinuxBlockObject *object)
138
UDisksMountMonitor *mount_monitor;
139
UDisksLinuxDevice *device;
144
mount_monitor = udisks_daemon_get_mount_monitor (udisks_linux_block_object_get_daemon (object));
145
device = udisks_linux_block_object_get_device (object);
147
p = g_ptr_array_new ();
148
mounts = udisks_mount_monitor_get_mounts_for_dev (mount_monitor, g_udev_device_get_device_number (device->udev_device));
149
/* we are guaranteed that the list is sorted so if there are
150
* multiple mounts we'll always get the same order
152
for (l = mounts; l != NULL; l = l->next)
154
UDisksMount *mount = UDISKS_MOUNT (l->data);
155
if (udisks_mount_get_mount_type (mount) == UDISKS_MOUNT_TYPE_FILESYSTEM)
156
g_ptr_array_add (p, (gpointer) udisks_mount_get_mount_path (mount));
158
g_ptr_array_add (p, NULL);
159
udisks_filesystem_set_mount_points (UDISKS_FILESYSTEM (filesystem),
160
(const gchar *const *) p->pdata);
161
g_ptr_array_free (p, TRUE);
162
g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
163
g_list_free (mounts);
164
g_object_unref (device);
167
/* ---------------------------------------------------------------------------------------------------- */
169
static const gchar *well_known_filesystems[] =
191
is_in_filesystem_file (const gchar *filesystems_file,
194
gchar *filesystems = NULL;
195
GError *error = NULL;
196
gboolean ret = FALSE;
197
gchar **lines = NULL;
200
if (!g_file_get_contents (filesystems_file,
202
NULL, /* gsize *out_length */
205
udisks_warning ("Error reading %s: %s (%s %d)",
208
g_quark_to_string (error->domain),
210
g_error_free (error);
214
lines = g_strsplit (filesystems, "\n", -1);
215
for (n = 0; lines != NULL && lines[n] != NULL && !ret; n++)
219
g_strdelimit (lines[n], " \t", ' ');
220
g_strstrip (lines[n]);
221
tokens = g_strsplit (lines[n], " ", -1);
222
num_tokens = g_strv_length (tokens);
223
if (num_tokens == 1 && g_strcmp0 (tokens[0], fstype) == 0)
232
g_free (filesystems);
237
is_well_known_filesystem (const gchar *fstype)
239
gboolean ret = FALSE;
242
for (n = 0; well_known_filesystems[n] != NULL; n++)
244
if (g_strcmp0 (well_known_filesystems[n], fstype) == 0)
254
/* this is not a very efficient implementation but it's very rarely
255
* called so no real point in optimizing it...
258
is_allowed_filesystem (const gchar *fstype)
260
return is_well_known_filesystem (fstype) ||
261
is_in_filesystem_file ("/proc/filesystems", fstype) ||
262
is_in_filesystem_file ("/etc/filesystems", fstype);
265
/* ---------------------------------------------------------------------------------------------------- */
270
const gchar * const *defaults;
271
const gchar * const *allow;
272
const gchar * const *allow_uid_self;
273
const gchar * const *allow_gid_self;
276
/* ---------------------- vfat -------------------- */
278
static const gchar *vfat_defaults[] = { "uid=", "gid=", "shortname=mixed", "dmask=0077", "utf8=1", "showexec", "flush", NULL };
279
static const gchar *vfat_allow[] = { "flush", "utf8=", "shortname=", "umask=", "dmask=", "fmask=", "codepage=", "iocharset=", "usefree", "showexec", NULL };
280
static const gchar *vfat_allow_uid_self[] = { "uid=", NULL };
281
static const gchar *vfat_allow_gid_self[] = { "gid=", NULL };
283
/* ---------------------- ntfs -------------------- */
284
/* this is assuming that ntfs-3g is used */
286
static const gchar *ntfs_defaults[] = { "uid=", "gid=", "dmask=0077", "fmask=0177", NULL };
287
static const gchar *ntfs_allow[] = { "umask=", "dmask=", "fmask=", "locale=", "norecover", "ignore_case", "windows_names", "compression", "nocompression", NULL };
288
static const gchar *ntfs_allow_uid_self[] = { "uid=", NULL };
289
static const gchar *ntfs_allow_gid_self[] = { "gid=", NULL };
291
/* ---------------------- iso9660 -------------------- */
293
static const gchar *iso9660_defaults[] = { "uid=", "gid=", "iocharset=utf8", "mode=0400", "dmode=0500", NULL };
294
static const gchar *iso9660_allow[] = { "norock", "nojoliet", "iocharset=", "mode=", "dmode=", NULL };
295
static const gchar *iso9660_allow_uid_self[] = { "uid=", NULL };
296
static const gchar *iso9660_allow_gid_self[] = { "gid=", NULL };
298
/* ---------------------- udf -------------------- */
300
static const gchar *udf_defaults[] = { "uid=", "gid=", "iocharset=utf8", "umask=0077", NULL };
301
static const gchar *udf_allow[] = { "iocharset=", "umask=", NULL };
302
static const gchar *udf_allow_uid_self[] = { "uid=", NULL };
303
static const gchar *udf_allow_gid_self[] = { "gid=", NULL };
305
/* ------------------------------------------------ */
306
/* TODO: support context= */
308
static const gchar *any_allow[] = { "exec", "noexec", "nodev", "nosuid", "atime", "noatime", "nodiratime", "ro", "rw", "sync", "dirsync", NULL };
310
static const FSMountOptions fs_mount_options[] =
312
{ "vfat", vfat_defaults, vfat_allow, vfat_allow_uid_self, vfat_allow_gid_self },
313
{ "ntfs", ntfs_defaults, ntfs_allow, ntfs_allow_uid_self, ntfs_allow_gid_self },
314
{ "iso9660", iso9660_defaults, iso9660_allow, iso9660_allow_uid_self, iso9660_allow_gid_self },
315
{ "udf", udf_defaults, udf_allow, udf_allow_uid_self, udf_allow_gid_self },
318
/* ------------------------------------------------ */
320
static int num_fs_mount_options = sizeof(fs_mount_options) / sizeof(FSMountOptions);
322
static const FSMountOptions *
323
find_mount_options_for_fs (const gchar *fstype)
326
const FSMountOptions *fsmo;
328
for (n = 0; n < num_fs_mount_options; n++)
330
fsmo = fs_mount_options + n;
331
if (g_strcmp0 (fsmo->fstype, fstype) == 0)
341
find_primary_gid (uid_t uid)
351
udisks_warning ("Error looking up uid %d: %m", uid);
361
is_uid_in_gid (uid_t uid,
366
static gid_t supplementary_groups[128];
367
int num_supplementary_groups = 128;
370
/* TODO: use some #define instead of harcoding some random number like 128 */
377
udisks_warning ("Error looking up uid %d: %m", uid);
380
if (pw->pw_gid == gid)
386
if (getgrouplist (pw->pw_name, pw->pw_gid, supplementary_groups, &num_supplementary_groups) < 0)
388
udisks_warning ("Error getting supplementary groups for uid %d: %m", uid);
392
for (n = 0; n < num_supplementary_groups; n++)
394
if (supplementary_groups[n] == gid)
406
is_mount_option_allowed (const FSMountOptions *fsmo,
420
/* first run through the allowed mount options */
423
for (n = 0; fsmo->allow != NULL && fsmo->allow[n] != NULL; n++)
425
ep = strstr (fsmo->allow[n], "=");
426
if (ep != NULL && ep[1] == '\0')
428
ep_len = ep - fsmo->allow[n] + 1;
429
if (strncmp (fsmo->allow[n], option, ep_len) == 0)
437
if (strcmp (fsmo->allow[n], option) == 0)
445
for (n = 0; any_allow[n] != NULL; n++)
447
ep = strstr (any_allow[n], "=");
448
if (ep != NULL && ep[1] == '\0')
450
ep_len = ep - any_allow[n] + 1;
451
if (strncmp (any_allow[n], option, ep_len) == 0)
459
if (strcmp (any_allow[n], option) == 0)
467
/* .. then check for mount options where the caller is allowed to pass
472
for (n = 0; fsmo->allow_uid_self != NULL && fsmo->allow_uid_self[n] != NULL; n++)
474
const gchar *r_mount_option = fsmo->allow_uid_self[n];
475
if (g_str_has_prefix (option, r_mount_option))
477
uid = strtol (option + strlen (r_mount_option), &endp, 10);
480
if (uid == caller_uid)
493
for (n = 0; fsmo->allow_gid_self != NULL && fsmo->allow_gid_self[n] != NULL; n++)
495
const gchar *r_mount_option = fsmo->allow_gid_self[n];
496
if (g_str_has_prefix (option, r_mount_option))
498
gid = strtol (option + strlen (r_mount_option), &endp, 10);
501
if (is_uid_in_gid (caller_uid, gid))
515
prepend_default_mount_options (const FSMountOptions *fsmo,
517
GVariant *given_options)
523
const gchar *option_string;
525
options = g_ptr_array_new ();
528
const gchar *const *defaults = fsmo->defaults;
530
for (n = 0; defaults != NULL && defaults[n] != NULL; n++)
532
const gchar *option = defaults[n];
534
if (strcmp (option, "uid=") == 0)
536
s = g_strdup_printf ("uid=%d", caller_uid);
537
g_ptr_array_add (options, s);
539
else if (strcmp (option, "gid=") == 0)
541
gid = find_primary_gid (caller_uid);
542
if (gid != (gid_t) - 1)
544
s = g_strdup_printf ("gid=%d", gid);
545
g_ptr_array_add (options, s);
550
g_ptr_array_add (options, g_strdup (option));
555
if (g_variant_lookup (given_options,
557
"&s", &option_string))
559
gchar **split_option_string;
560
split_option_string = g_strsplit (option_string, ",", -1);
561
for (n = 0; split_option_string[n] != NULL; n++)
562
g_ptr_array_add (options, split_option_string[n]); /* steals string */
563
g_free (split_option_string);
565
g_ptr_array_add (options, NULL);
567
return (char **) g_ptr_array_free (options, FALSE);
571
subst_str (const gchar *str,
578
parts = g_strsplit (str, from, 0);
579
result = g_strjoinv (to, parts);
585
subst_str_and_escape (const gchar *str,
589
gchar *quoted_and_escaped;
591
quoted_and_escaped = udisks_daemon_util_escape_and_quote (to);
592
ret = subst_str (str, from, quoted_and_escaped);
593
g_free (quoted_and_escaped);
597
/* ---------------------------------------------------------------------------------------------------- */
600
* calculate_fs_type: <internal>
601
* @block: A #UDisksBlock.
602
* @given_options: The a{sv} #GVariant.
603
* @error: Return location for error or %NULL.
605
* Calculates the file system type to use.
607
* Returns: A valid UTF-8 string with the filesystem type (may be "auto") or %NULL if @error is set. Free with g_free().
610
calculate_fs_type (UDisksBlock *block,
611
GVariant *given_options,
614
gchar *fs_type_to_use = NULL;
615
const gchar *probed_fs_type = NULL;
616
const gchar *requested_fs_type;
618
probed_fs_type = NULL;
620
probed_fs_type = udisks_block_get_id_type (block);
622
if (g_variant_lookup (given_options,
624
"&s", &requested_fs_type) &&
625
strlen (requested_fs_type) > 0)
627
/* If the user requests the filesystem type, error out unless the
630
* - well-known [1]; or
631
* - in the /proc/filesystems file; or
632
* - in the /etc/filesystems file
634
* in that order. We do this because mount(8) on Linux allows
635
* loading any arbitrary kernel module (when invoked as root) by
636
* passing something appropriate to the -t option. So we have to
637
* validate whatever we pass...
639
* See https://bugs.freedesktop.org/show_bug.cgi?id=32232 for more
642
* [1] : since /etc/filesystems may be horribly out of date and
643
* not contain e.g. ext4
645
if (g_strcmp0 (requested_fs_type, "auto") != 0)
647
if (!is_allowed_filesystem (requested_fs_type))
651
UDISKS_ERROR_OPTION_NOT_PERMITTED,
652
"Requested filesystem type `%s' is neither well-known nor "
653
"in /proc/filesystems nor in /etc/filesystems",
659
/* TODO: maybe check that it's compatible with probed_fs_type */
660
fs_type_to_use = g_strdup (requested_fs_type);
664
if (probed_fs_type != NULL && strlen (probed_fs_type) > 0)
665
fs_type_to_use = g_strdup (probed_fs_type);
667
fs_type_to_use = g_strdup ("auto");
671
g_assert (fs_type_to_use == NULL || g_utf8_validate (fs_type_to_use, -1, NULL));
673
return fs_type_to_use;
677
* calculate_mount_options: <internal>
678
* @daemon: A #UDisksDaemon.
679
* @block: A #UDisksBlock.
680
* @caller_uid: The uid of the caller making the request.
681
* @fs_type: The filesystem type to use or %NULL.
682
* @options: Options requested by the caller.
683
* @error: Return location for error or %NULL.
685
* Calculates the mount option string to use. Ensures (by returning an
686
* error) that only safe options are used.
688
* Returns: A string with mount options or %NULL if @error is set. Free with g_free().
691
calculate_mount_options (UDisksDaemon *daemon,
694
const gchar *fs_type,
698
const FSMountOptions *fsmo;
699
gchar **options_to_use;
700
gchar *options_to_use_str;
704
options_to_use = NULL;
705
options_to_use_str = NULL;
707
fsmo = find_mount_options_for_fs (fs_type);
709
/* always prepend some reasonable default mount options; these are
710
* chosen here; the user can override them if he wants to
712
options_to_use = prepend_default_mount_options (fsmo, caller_uid, options);
714
/* validate mount options */
715
str = g_string_new ("uhelper=udisks2,nodev,nosuid");
716
for (n = 0; options_to_use[n] != NULL; n++)
718
const gchar *option = options_to_use[n];
720
/* avoid attacks like passing "shortname=lower,uid=0" as a single mount option */
721
if (strstr (option, ",") != NULL)
725
UDISKS_ERROR_OPTION_NOT_PERMITTED,
726
"Malformed mount option `%s'",
728
g_string_free (str, TRUE);
732
/* first check if the mount option is allowed */
733
if (!is_mount_option_allowed (fsmo, option, caller_uid))
737
UDISKS_ERROR_OPTION_NOT_PERMITTED,
738
"Mount option `%s' is not allowed",
740
g_string_free (str, TRUE);
744
g_string_append_c (str, ',');
745
g_string_append (str, option);
747
options_to_use_str = g_string_free (str, FALSE);
750
g_strfreev (options_to_use);
752
g_assert (options_to_use_str == NULL || g_utf8_validate (options_to_use_str, -1, NULL));
754
return options_to_use_str;
757
/* ---------------------------------------------------------------------------------------------------- */
760
ensure_utf8 (const gchar *s)
765
if (!g_utf8_validate (s, -1, &end))
769
/* TODO: could possibly return a nicer UTF-8 string */
770
pos = (gint) (end - s);
771
tmp = g_strndup (s, end - s);
772
ret = g_strdup_printf ("%s (Invalid UTF-8 at byte %d)", tmp, pos);
783
/* ---------------------------------------------------------------------------------------------------- */
786
add_acl (const gchar *path,
790
gboolean ret = FALSE;
793
acl_permset_t permset;
795
acl = acl_get_file(path, ACL_TYPE_ACCESS);
797
acl_create_entry (&acl, &entry) == -1 ||
798
acl_set_tag_type (entry, ACL_USER) == -1 ||
799
acl_set_qualifier (entry, &uid) == -1 ||
800
acl_get_permset (entry, &permset) == -1 ||
801
acl_add_perm (permset, ACL_READ|ACL_EXECUTE) == -1 ||
802
acl_calc_mask (&acl) == -1 ||
803
acl_set_file (path, ACL_TYPE_ACCESS, acl) == -1)
806
"Adding read ACL for uid %d to `%s' failed: %m",
808
chown(path, uid, -1);
820
* calculate_mount_point: <internal>
821
* @dameon: A #UDisksDaemon.
822
* @block: A #UDisksBlock.
823
* @uid: user id of the calling user
824
* @gid: group id of the calling user
825
* @user_name: user name of the calling user
826
* @fs_type: The file system type to mount with
827
* @error: Return location for error or %NULL.
829
* Calculates the mount point to use.
831
* Returns: A UTF-8 string with the mount point to use or %NULL if @error is set. Free with g_free().
834
calculate_mount_point (UDisksDaemon *daemon,
838
const gchar *user_name,
839
const gchar *fs_type,
842
UDisksLinuxBlockObject *object = NULL;
843
gboolean fs_shared = FALSE;
844
const gchar *label = NULL;
845
const gchar *uuid = NULL;
846
gchar *escaped_user_name = NULL;
847
gchar *mount_dir = NULL;
848
gchar *mount_point = NULL;
849
gchar *orig_mount_point;
858
label = udisks_block_get_id_label (block);
859
uuid = udisks_block_get_id_uuid (block);
862
object = udisks_daemon_util_dup_object (block, NULL);
865
UDisksLinuxDevice *device = udisks_linux_block_object_get_device (object);
868
if (device->udev_device != NULL)
870
/* TODO: maybe introduce Block:HintFilesystemShared instead of pulling it directly from the udev device */
871
fs_shared = g_udev_device_get_property_as_boolean (device->udev_device, "UDISKS_FILESYSTEM_SHARED");
873
g_object_unref (device);
877
/* If we know the user-name and it doesn't have any '/' character in
878
* it, mount in /media/$USER
880
if (!fs_shared && (user_name != NULL && strstr (user_name, "/") == NULL))
882
mount_dir = g_strdup_printf ("/media/%s", user_name);
883
if (!g_file_test (mount_dir, G_FILE_TEST_EXISTS))
885
/* First ensure that /media exists */
886
if (!g_file_test ("/media", G_FILE_TEST_EXISTS))
888
if (g_mkdir ("/media", 0755) != 0)
893
"Error creating directory /media: %m");
897
/* Then create the per-user /media/$USER */
898
if (g_mkdir (mount_dir, 0700) != 0)
903
"Error creating directory `%s': %m",
907
/* Finally, add the read+execute ACL for $USER */
908
if (!add_acl (mount_dir, uid, error))
910
if (rmdir (mount_dir) != 0)
911
udisks_warning ("Error calling rmdir() on %s: %m", mount_dir);
916
/* otherwise fall back to mounting in /media */
917
if (mount_dir == NULL)
918
mount_dir = g_strdup ("/media");
920
/* NOTE: UTF-8 has the nice property that valid UTF-8 strings only contains
921
* the byte 0x2F if it's for the '/' character (U+002F SOLIDUS).
923
* See http://en.wikipedia.org/wiki/UTF-8 for details.
925
if (label != NULL && strlen (label) > 0)
927
str = g_string_new (NULL);
928
g_string_append_printf (str, "%s/", mount_dir);
929
s = ensure_utf8 (label);
930
for (n = 0; s[n] != '\0'; n++)
934
g_string_append_c (str, '_');
936
g_string_append_c (str, c);
938
mount_point = g_string_free (str, FALSE);
941
else if (uuid != NULL && strlen (uuid) > 0)
943
str = g_string_new (NULL);
944
g_string_append_printf (str, "%s/", mount_dir);
945
s = ensure_utf8 (uuid);
946
for (n = 0; s[n] != '\0'; n++)
950
g_string_append_c (str, '_');
952
g_string_append_c (str, c);
954
mount_point = g_string_free (str, FALSE);
959
mount_point = g_strdup_printf ("%s/disk", mount_dir);
962
/* ... then uniqify the mount point */
963
orig_mount_point = g_strdup (mount_point);
967
if (!g_file_test (mount_point, G_FILE_TEST_EXISTS))
973
g_free (mount_point);
974
mount_point = g_strdup_printf ("%s%d", orig_mount_point, n++);
977
g_free (orig_mount_point);
981
g_clear_object (&object);
982
g_free (escaped_user_name);
986
/* ---------------------------------------------------------------------------------------------------- */
989
has_option (const gchar *options,
992
gboolean ret = FALSE;
996
tokens = g_strsplit (options, ",", -1);
997
for (n = 0; tokens != NULL && tokens[n] != NULL; n++)
999
if (g_strcmp0 (tokens[n], option) == 0)
1005
g_strfreev (tokens);
1012
is_in_fstab (UDisksBlock *block,
1013
const gchar *fstab_path,
1014
gchar **out_mount_point,
1015
gchar **out_mount_options)
1024
f = fopen (fstab_path, "r");
1027
udisks_warning ("Error opening fstab file %s: %m", fstab_path);
1031
while ((m = getmntent_r (f, &mbuf, buf, sizeof (buf))) != NULL && !ret)
1037
if (g_str_has_prefix (m->mnt_fsname, "UUID="))
1039
device = g_strdup_printf ("/dev/disk/by-uuid/%s", m->mnt_fsname + 5);
1041
else if (g_str_has_prefix (m->mnt_fsname, "LABEL="))
1043
device = g_strdup_printf ("/dev/disk/by-label/%s", m->mnt_fsname + 6);
1045
else if (g_str_has_prefix (m->mnt_fsname, "/dev"))
1047
device = g_strdup (m->mnt_fsname);
1051
/* ignore non-device entries */
1055
if (stat (device, &sb) != 0)
1057
udisks_debug ("Error statting %s (for entry %s): %m", device, m->mnt_fsname);
1060
if (!S_ISBLK (sb.st_mode))
1062
udisks_debug ("Device %s (for entry %s) is not a block device", device, m->mnt_fsname);
1066
/* udisks_debug ("device %d:%d for entry %s", major (sb.st_rdev), minor (sb.st_rdev), m->mnt_fsname); */
1068
if (udisks_block_get_device_number (block) == sb.st_rdev)
1071
if (out_mount_point != NULL)
1072
*out_mount_point = g_strdup (m->mnt_dir);
1073
if (out_mount_options != NULL)
1074
*out_mount_options = g_strdup (m->mnt_opts);
1087
/* returns TRUE if, and only if, device is referenced in e.g. /etc/fstab
1089
* TODO: check all files in /etc/fstab.d (it's a non-standard Linux extension)
1090
* TODO: check if systemd has a specific "unit" for the device
1093
is_system_managed (UDisksBlock *block,
1094
gchar **out_mount_point,
1095
gchar **out_mount_options)
1101
/* First, check /etc/fstab */
1102
if (is_in_fstab (block, "/etc/fstab", out_mount_point, out_mount_options))
1111
/* ---------------------------------------------------------------------------------------------------- */
1113
/* runs in thread dedicated to handling @invocation */
1115
handle_mount (UDisksFilesystem *filesystem,
1116
GDBusMethodInvocation *invocation,
1119
UDisksObject *object;
1121
UDisksDaemon *daemon;
1126
const gchar * const *existing_mount_points;
1127
const gchar *probed_fs_usage;
1128
gchar *fs_type_to_use;
1129
gchar *mount_options_to_use;
1130
gchar *mount_point_to_use;
1131
gchar *fstab_mount_options;
1132
gchar *escaped_fs_type_to_use;
1133
gchar *escaped_mount_options_to_use;
1134
gchar *escaped_mount_point_to_use;
1135
gchar *error_message;
1136
gchar *caller_user_name;
1138
const gchar *action_id;
1139
const gchar *message;
1140
gboolean system_managed;
1141
gchar *escaped_device = NULL;
1144
error_message = NULL;
1145
fs_type_to_use = NULL;
1146
mount_options_to_use = NULL;
1147
mount_point_to_use = NULL;
1148
fstab_mount_options = NULL;
1149
escaped_fs_type_to_use = NULL;
1150
escaped_mount_options_to_use = NULL;
1151
escaped_mount_point_to_use = NULL;
1152
caller_user_name = NULL;
1153
system_managed = FALSE;
1155
/* only allow a single call at a time */
1156
g_mutex_lock (&UDISKS_LINUX_FILESYSTEM (filesystem)->lock);
1159
object = udisks_daemon_util_dup_object (filesystem, &error);
1162
g_dbus_method_invocation_take_error (invocation, error);
1166
block = udisks_object_peek_block (object);
1167
daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object));
1168
state = udisks_daemon_get_state (daemon);
1170
/* check if mount point is managed by e.g. /etc/fstab or similar */
1171
if (is_system_managed (block, &mount_point_to_use, &fstab_mount_options))
1173
system_managed = TRUE;
1176
/* First, fail if the device is already mounted */
1177
existing_mount_points = udisks_filesystem_get_mount_points (filesystem);
1178
if (existing_mount_points != NULL && g_strv_length ((gchar **) existing_mount_points) > 0)
1182
str = g_string_new (NULL);
1183
for (n = 0; existing_mount_points[n] != NULL; n++)
1186
g_string_append (str, ", ");
1187
g_string_append_printf (str, "`%s'", existing_mount_points[n]);
1189
g_dbus_method_invocation_return_error (invocation,
1191
UDISKS_ERROR_ALREADY_MOUNTED,
1192
"Device %s is already mounted at %s.\n",
1193
udisks_block_get_device (block),
1195
g_string_free (str, TRUE);
1200
if (!udisks_daemon_util_get_caller_uid_sync (daemon,
1202
NULL /* GCancellable */,
1208
g_dbus_method_invocation_return_gerror (invocation, error);
1209
g_error_free (error);
1214
if (!udisks_daemon_util_get_caller_pid_sync (daemon,
1216
NULL /* GCancellable */,
1220
g_dbus_method_invocation_return_gerror (invocation, error);
1221
g_error_free (error);
1228
gboolean mount_fstab_as_root = FALSE;
1230
if (!has_option (fstab_mount_options, "x-udisks-auth"))
1232
action_id = "org.freedesktop.udisks2.filesystem-mount";
1233
/* Translators: Shown in authentication dialog when the user
1234
* requests mounting a filesystem.
1236
* Do not translate $(drive), it's a placeholder and
1237
* will be replaced by the name of the drive/device in question
1239
message = N_("Authentication is required to mount $(drive)");
1240
if (!udisks_daemon_util_setup_by_user (daemon, object, caller_uid))
1242
if (udisks_block_get_hint_system (block))
1244
action_id = "org.freedesktop.udisks2.filesystem-mount-system";
1246
else if (!udisks_daemon_util_on_same_seat (daemon, object, caller_pid))
1248
action_id = "org.freedesktop.udisks2.filesystem-mount-other-seat";
1252
if (!udisks_daemon_util_check_authorization_sync (daemon,
1259
mount_fstab_as_root = TRUE;
1262
if (!g_file_test (mount_point_to_use, G_FILE_TEST_IS_DIR))
1264
if (g_mkdir_with_parents (mount_point_to_use, 0755) != 0)
1266
g_dbus_method_invocation_return_error (invocation,
1268
UDISKS_ERROR_FAILED,
1269
"Error creating directory `%s' to be used for mounting %s: %m",
1271
udisks_block_get_device (block));
1276
escaped_mount_point_to_use = udisks_daemon_util_escape_and_quote (mount_point_to_use);
1278
if (!udisks_daemon_launch_spawned_job_sync (daemon,
1280
"filesystem-mount", caller_uid,
1281
NULL, /* GCancellable */
1282
mount_fstab_as_root ? 0 : caller_uid, /* uid_t run_as_uid */
1283
mount_fstab_as_root ? 0 : caller_uid, /* uid_t run_as_euid */
1286
NULL, /* input_string */
1288
escaped_mount_point_to_use))
1290
/* mount(8) exits with status 1 on "incorrect invocation or permissions" - if this is
1291
* is so, try as as root */
1292
if (!mount_fstab_as_root && WIFEXITED (status) && WEXITSTATUS (status) == 1)
1294
if (!udisks_daemon_util_check_authorization_sync (daemon,
1296
"org.freedesktop.udisks2.filesystem-fstab",
1298
/* Translators: Shown in authentication dialog when the
1299
* user requests mounting a filesystem that is in
1300
* /etc/fstab file with the x-udisks-auth option.
1302
* Do not translate $(drive), it's a
1303
* placeholder and will be replaced by the name of
1304
* the drive/device in question
1306
* Do not translate /etc/fstab
1308
N_("Authentication is required to mount $(drive) referenced in the /etc/fstab file"),
1311
mount_fstab_as_root = TRUE;
1312
goto mount_fstab_again;
1315
g_dbus_method_invocation_return_error (invocation,
1317
UDISKS_ERROR_FAILED,
1318
"Error mounting system-managed device %s: %s",
1319
udisks_block_get_device (block),
1323
udisks_notice ("Mounted %s (system) at %s on behalf of uid %d",
1324
udisks_block_get_device (block),
1328
/* update the mounted-fs file */
1329
udisks_state_add_mounted_fs (state,
1331
udisks_block_get_device_number (block),
1333
TRUE); /* fstab_mounted */
1335
udisks_filesystem_complete_mount (filesystem, invocation, mount_point_to_use);
1339
/* Then fail if the device is not mountable - we actually allow mounting
1340
* devices that are not probed since since it could be that we just
1341
* don't have the data in the udev database but the device has a
1342
* filesystem *anyway*...
1344
* For example, this applies to PC floppy devices - automatically
1345
* probing for media them creates annoying noise. So they won't
1346
* appear in the udev database.
1348
probed_fs_usage = NULL;
1350
probed_fs_usage = udisks_block_get_id_usage (block);
1351
if (probed_fs_usage != NULL && strlen (probed_fs_usage) > 0 &&
1352
g_strcmp0 (probed_fs_usage, "filesystem") != 0)
1354
g_dbus_method_invocation_return_error (invocation,
1356
UDISKS_ERROR_FAILED,
1357
"Cannot mount block device %s with probed usage `%s' - expected `filesystem'",
1358
udisks_block_get_device (block),
1363
/* calculate filesystem type (guaranteed to be valid UTF-8) */
1365
fs_type_to_use = calculate_fs_type (block,
1368
if (fs_type_to_use == NULL)
1370
g_dbus_method_invocation_return_gerror (invocation, error);
1371
g_error_free (error);
1375
/* calculate mount options (guaranteed to be valid UTF-8) */
1377
mount_options_to_use = calculate_mount_options (daemon,
1383
if (mount_options_to_use == NULL)
1385
g_dbus_method_invocation_return_gerror (invocation, error);
1386
g_error_free (error);
1390
/* Now, check that the user is actually authorized to mount the
1391
* device. Need to do this before calculating a mount point since we
1392
* may be racing with other threads...
1394
action_id = "org.freedesktop.udisks2.filesystem-mount";
1395
/* Translators: Shown in authentication dialog when the user
1396
* requests mounting a filesystem.
1398
* Do not translate $(drive), it's a placeholder and
1399
* will be replaced by the name of the drive/device in question
1401
message = N_("Authentication is required to mount $(drive)");
1402
if (!udisks_daemon_util_setup_by_user (daemon, object, caller_uid))
1404
if (udisks_block_get_hint_system (block))
1406
action_id = "org.freedesktop.udisks2.filesystem-mount-system";
1408
else if (!udisks_daemon_util_on_same_seat (daemon, object, caller_pid))
1410
action_id = "org.freedesktop.udisks2.filesystem-mount-other-seat";
1414
if (!udisks_daemon_util_check_authorization_sync (daemon,
1422
/* calculate mount point (guaranteed to be valid UTF-8) */
1424
mount_point_to_use = calculate_mount_point (daemon,
1431
if (mount_point_to_use == NULL)
1433
g_dbus_method_invocation_return_gerror (invocation, error);
1434
g_error_free (error);
1438
/* create the mount point */
1439
if (g_mkdir (mount_point_to_use, 0700) != 0)
1441
g_dbus_method_invocation_return_error (invocation,
1443
UDISKS_ERROR_FAILED,
1444
"Error creating mount point `%s': %m",
1445
mount_point_to_use);
1449
escaped_fs_type_to_use = udisks_daemon_util_escape_and_quote (fs_type_to_use);
1450
escaped_mount_options_to_use = udisks_daemon_util_escape_and_quote (mount_options_to_use);
1451
escaped_mount_point_to_use = udisks_daemon_util_escape_and_quote (mount_point_to_use);
1452
escaped_device = udisks_daemon_util_escape_and_quote (udisks_block_get_device (block));
1455
if (!udisks_daemon_launch_spawned_job_sync (daemon,
1457
"filesystem-mount", caller_uid,
1458
NULL, /* GCancellable */
1459
0, /* uid_t run_as_uid */
1460
0, /* uid_t run_as_euid */
1461
NULL, /* gint *out_status */
1463
NULL, /* input_string */
1464
"mount -t %s -o %s %s %s",
1465
escaped_fs_type_to_use,
1466
escaped_mount_options_to_use,
1468
escaped_mount_point_to_use))
1470
/* ugh, something went wrong.. we need to clean up the created mount point */
1471
if (g_rmdir (mount_point_to_use) != 0)
1472
udisks_warning ("Error removing directory %s: %m", mount_point_to_use);
1473
g_dbus_method_invocation_return_error (invocation,
1475
UDISKS_ERROR_FAILED,
1476
"Error mounting %s at %s: %s",
1477
udisks_block_get_device (block),
1483
/* update the mounted-fs file */
1484
udisks_state_add_mounted_fs (state,
1486
udisks_block_get_device_number (block),
1488
FALSE); /* fstab_mounted */
1490
udisks_notice ("Mounted %s at %s on behalf of uid %d",
1491
udisks_block_get_device (block),
1495
udisks_filesystem_complete_mount (filesystem, invocation, mount_point_to_use);
1498
g_free (escaped_device);
1499
g_free (error_message);
1500
g_free (escaped_fs_type_to_use);
1501
g_free (escaped_mount_options_to_use);
1502
g_free (escaped_mount_point_to_use);
1503
g_free (fs_type_to_use);
1504
g_free (mount_options_to_use);
1505
g_free (mount_point_to_use);
1506
g_free (fstab_mount_options);
1507
g_free (caller_user_name);
1508
g_clear_object (&object);
1510
/* only allow a single call at a time */
1511
g_mutex_unlock (&UDISKS_LINUX_FILESYSTEM (filesystem)->lock);
1513
return TRUE; /* returning TRUE means that we handled the method invocation */
1516
/* ---------------------------------------------------------------------------------------------------- */
1519
get_error_code_for_umount (gint exit_status,
1520
const gchar *error_message)
1522
if (strstr (error_message, "device is busy") != NULL ||
1523
strstr (error_message, "target is busy") != NULL)
1524
return UDISKS_ERROR_DEVICE_BUSY;
1526
return UDISKS_ERROR_FAILED;
1529
/* runs in thread dedicated to handling @invocation */
1531
handle_unmount (UDisksFilesystem *filesystem,
1532
GDBusMethodInvocation *invocation,
1535
UDisksObject *object;
1537
UDisksDaemon *daemon;
1540
gchar *fstab_mount_options;
1541
gchar *escaped_mount_point;
1543
uid_t mounted_by_uid;
1546
gchar *error_message;
1547
const gchar *const *mount_points;
1550
gboolean system_managed;
1551
gboolean fstab_mounted;
1552
gchar *escaped_device = NULL;
1555
fstab_mount_options = NULL;
1556
escaped_mount_point = NULL;
1557
error_message = NULL;
1560
/* only allow a single call at a time */
1561
g_mutex_lock (&UDISKS_LINUX_FILESYSTEM (filesystem)->lock);
1564
object = udisks_daemon_util_dup_object (filesystem, &error);
1567
g_dbus_method_invocation_take_error (invocation, error);
1571
block = udisks_object_peek_block (object);
1572
daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object));
1573
state = udisks_daemon_get_state (daemon);
1574
system_managed = FALSE;
1576
if (options != NULL)
1578
g_variant_lookup (options,
1584
mount_points = udisks_filesystem_get_mount_points (filesystem);
1585
if (mount_points == NULL || g_strv_length ((gchar **) mount_points) == 0)
1587
g_dbus_method_invocation_return_error (invocation,
1589
UDISKS_ERROR_NOT_MOUNTED,
1590
"Device `%s' is not mounted",
1591
udisks_block_get_device (block));
1596
if (!udisks_daemon_util_get_caller_uid_sync (daemon, invocation, NULL, &caller_uid, NULL, NULL, &error))
1598
g_dbus_method_invocation_return_gerror (invocation, error);
1599
g_error_free (error);
1603
/* check if mount point is managed by e.g. /etc/fstab or similar */
1604
if (is_system_managed (block, &mount_point, &fstab_mount_options))
1606
system_managed = TRUE;
1609
/* if system-managed (e.g. referenced in /etc/fstab or similar) and
1610
* with the option x-udisks-auth, just run umount(8) as the
1613
if (system_managed && has_option (fstab_mount_options, "x-udisks-auth"))
1615
gboolean unmount_fstab_as_root;
1617
unmount_fstab_as_root = FALSE;
1618
unmount_fstab_again:
1619
escaped_mount_point = udisks_daemon_util_escape_and_quote (mount_point);
1620
/* right now -l is the only way to "force unmount" file systems... */
1621
if (!udisks_daemon_launch_spawned_job_sync (daemon,
1623
"filesystem-unmount", caller_uid,
1624
NULL, /* GCancellable */
1625
unmount_fstab_as_root ? 0 : caller_uid, /* uid_t run_as_uid */
1626
unmount_fstab_as_root ? 0 : caller_uid, /* uid_t run_as_euid */
1629
NULL, /* input_string */
1631
opt_force ? "-l" : "",
1632
escaped_mount_point))
1634
/* umount(8) does not (yet) have a specific exits status for
1635
* "insufficient permissions" so just try again as root
1637
* TODO: file bug asking for such an exit status
1639
if (!unmount_fstab_as_root && WIFEXITED (status) && WEXITSTATUS (status) != 0)
1641
if (!udisks_daemon_util_check_authorization_sync (daemon,
1643
"org.freedesktop.udisks2.filesystem-fstab",
1645
/* Translators: Shown in authentication dialog when the
1646
* user requests unmounting a filesystem that is in
1647
* /etc/fstab file with the x-udisks-auth option.
1649
* Do not translate $(drive), it's a
1650
* placeholder and will be replaced by the name of
1651
* the drive/device in question
1653
* Do not translate /etc/fstab
1655
N_("Authentication is required to unmount $(drive) referenced in the /etc/fstab file"),
1658
unmount_fstab_as_root = TRUE;
1659
goto unmount_fstab_again;
1662
g_dbus_method_invocation_return_error (invocation,
1664
get_error_code_for_umount (status, error_message),
1665
"Error unmounting system-managed device %s: %s",
1666
udisks_block_get_device (block),
1670
udisks_notice ("Unmounted %s (system) from %s on behalf of uid %d",
1671
udisks_block_get_device (block),
1674
udisks_filesystem_complete_unmount (filesystem, invocation);
1679
mount_point = udisks_state_find_mounted_fs (state,
1680
udisks_block_get_device_number (block),
1683
if (mount_point == NULL)
1685
/* allow unmounting stuff not mentioned in mounted-fs, but treat it like root mounted it */
1689
if (caller_uid != 0 && (caller_uid != mounted_by_uid))
1691
const gchar *action_id;
1692
const gchar *message;
1694
action_id = "org.freedesktop.udisks2.filesystem-unmount-others";
1695
/* Translators: Shown in authentication dialog when the user
1696
* requests unmounting a filesystem previously mounted by
1699
* Do not translate $(drive), it's a placeholder and
1700
* will be replaced by the name of the drive/device in question
1702
message = N_("Authentication is required to unmount $(drive) mounted by another user");
1704
if (!udisks_daemon_util_check_authorization_sync (daemon,
1713
escaped_device = udisks_daemon_util_escape_and_quote (udisks_block_get_device (block));
1715
/* otherwise go ahead and unmount the filesystem */
1716
if (mount_point != NULL)
1718
escaped_mount_point = udisks_daemon_util_escape_and_quote (mount_point);
1719
rc = udisks_daemon_launch_spawned_job_sync (daemon,
1721
"filesystem-unmount", caller_uid,
1722
NULL, /* GCancellable */
1723
0, /* uid_t run_as_uid */
1724
0, /* uid_t run_as_euid */
1725
NULL, /* gint *out_status */
1727
NULL, /* input_string */
1729
opt_force ? "-l" : "",
1730
escaped_mount_point);
1734
/* mount_point == NULL */
1735
rc = udisks_daemon_launch_spawned_job_sync (daemon,
1737
"filesystem-unmount", caller_uid,
1738
NULL, /* GCancellable */
1739
0, /* uid_t run_as_uid */
1740
0, /* uid_t run_as_euid */
1743
NULL, /* input_string */
1745
opt_force ? "-l" : "",
1751
g_dbus_method_invocation_return_error (invocation,
1753
get_error_code_for_umount (status, error_message),
1754
"Error unmounting %s: %s",
1755
udisks_block_get_device (block),
1760
/* OK, filesystem unmounted.. the state/cleanup routines will remove the mountpoint for us */
1762
udisks_notice ("Unmounted %s on behalf of uid %d",
1763
udisks_block_get_device (block),
1766
udisks_filesystem_complete_unmount (filesystem, invocation);
1769
g_free (escaped_device);
1770
g_free (error_message);
1771
g_free (escaped_mount_point);
1772
g_free (mount_point);
1773
g_free (fstab_mount_options);
1774
g_clear_object (&object);
1776
g_mutex_unlock (&UDISKS_LINUX_FILESYSTEM (filesystem)->lock);
1781
/* ---------------------------------------------------------------------------------------------------- */
1784
on_set_label_job_completed (UDisksJob *job,
1786
const gchar *message,
1789
GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
1790
UDisksFilesystem *filesystem;
1792
filesystem = UDISKS_FILESYSTEM (g_dbus_method_invocation_get_user_data (invocation));
1795
udisks_filesystem_complete_set_label (filesystem, invocation);
1797
g_dbus_method_invocation_return_error (invocation,
1799
UDISKS_ERROR_FAILED,
1800
"Error setting label: %s",
1804
/* runs in thread dedicated to handling method call */
1806
handle_set_label (UDisksFilesystem *filesystem,
1807
GDBusMethodInvocation *invocation,
1812
UDisksObject *object;
1813
UDisksDaemon *daemon;
1814
const gchar *probed_fs_usage;
1815
const gchar *probed_fs_type;
1816
const FSInfo *fs_info;
1818
const gchar *action_id;
1819
const gchar *message;
1832
object = udisks_daemon_util_dup_object (filesystem, &error);
1835
g_dbus_method_invocation_take_error (invocation, error);
1839
daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object));
1840
block = udisks_object_peek_block (object);
1843
if (!udisks_daemon_util_get_caller_pid_sync (daemon,
1845
NULL /* GCancellable */,
1849
g_dbus_method_invocation_return_gerror (invocation, error);
1850
g_error_free (error);
1855
if (!udisks_daemon_util_get_caller_uid_sync (daemon,
1857
NULL /* GCancellable */,
1863
g_dbus_method_invocation_return_gerror (invocation, error);
1864
g_error_free (error);
1868
probed_fs_usage = udisks_block_get_id_usage (block);
1869
probed_fs_type = udisks_block_get_id_type (block);
1871
if (g_strcmp0 (probed_fs_usage, "filesystem") != 0)
1873
g_dbus_method_invocation_return_error (invocation,
1875
UDISKS_ERROR_NOT_SUPPORTED,
1876
"Cannot change label on device of type %s",
1881
fs_info = get_fs_info (probed_fs_type);
1883
if (fs_info == NULL || fs_info->command_change_label == NULL)
1885
g_dbus_method_invocation_return_error (invocation,
1887
UDISKS_ERROR_NOT_SUPPORTED,
1888
"Don't know how to change label on device of type %s:%s",
1894
/* VFAT does not allow some characters; as mlabel hangs with interactive
1895
* question in this case, check in advance */
1896
if (g_strcmp0 (probed_fs_type, "vfat") == 0)
1898
const gchar *forbidden = "\"*/:<>?\\|";
1900
for (n = 0; forbidden[n] != 0; n++)
1902
if (strchr (label, forbidden[n]) != NULL)
1904
g_dbus_method_invocation_return_error (invocation,
1906
UDISKS_ERROR_NOT_SUPPORTED,
1907
"character '%c' not supported in VFAT labels",
1914
/* Fail if the device is already mounted and the tools/drivers doesn't
1915
* support changing the label in that case
1917
if (filesystem != NULL && !fs_info->supports_online_label_rename)
1919
const gchar * const *existing_mount_points;
1920
existing_mount_points = udisks_filesystem_get_mount_points (filesystem);
1921
if (existing_mount_points != NULL && g_strv_length ((gchar **) existing_mount_points) > 0)
1923
g_dbus_method_invocation_return_error (invocation,
1925
UDISKS_ERROR_NOT_SUPPORTED,
1926
"Cannot change label on mounted device of type %s:%s.\n",
1933
action_id = "org.freedesktop.udisks2.modify-device";
1934
/* Translators: Shown in authentication dialog when the user
1935
* requests changing the filesystem label.
1937
* Do not translate $(drive), it's a placeholder and
1938
* will be replaced by the name of the drive/device in question
1940
message = N_("Authentication is required to change the filesystem label on $(drive)");
1941
if (!udisks_daemon_util_setup_by_user (daemon, object, caller_uid))
1943
if (udisks_block_get_hint_system (block))
1945
action_id = "org.freedesktop.udisks2.modify-device-system";
1947
else if (!udisks_daemon_util_on_same_seat (daemon, UDISKS_OBJECT (object), caller_pid))
1949
action_id = "org.freedesktop.udisks2.modify-device-other-seat";
1953
/* Check that the user is actually authorized to change the
1956
if (!udisks_daemon_util_check_authorization_sync (daemon,
1964
if (fs_info->command_clear_label != NULL && strlen (label) == 0)
1966
command = subst_str_and_escape (fs_info->command_clear_label, "$DEVICE", udisks_block_get_device (block));
1970
tmp = subst_str_and_escape (fs_info->command_change_label, "$DEVICE", udisks_block_get_device (block));
1971
command = subst_str_and_escape (tmp, "$LABEL", label);
1975
job = udisks_daemon_launch_spawned_job (daemon,
1977
"filesystem-modify", caller_uid,
1978
NULL, /* cancellable */
1979
0, /* uid_t run_as_uid */
1980
0, /* uid_t run_as_euid */
1981
NULL, /* input_string */
1983
g_signal_connect (job,
1985
G_CALLBACK (on_set_label_job_completed),
1990
g_clear_object (&object);
1991
return TRUE; /* returning TRUE means that we handled the method invocation */
1994
/* ---------------------------------------------------------------------------------------------------- */
1997
filesystem_iface_init (UDisksFilesystemIface *iface)
1999
iface->handle_mount = handle_mount;
2000
iface->handle_unmount = handle_unmount;
2001
iface->handle_set_label = handle_set_label;