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>
26
#include <sys/types.h>
35
#include "udisksdaemon.h"
36
#include "udisksdaemonutil.h"
37
#include "udiskscleanup.h"
38
#include "udiskslogging.h"
39
#include "udiskslinuxblockobject.h"
40
#include "udiskslinuxdriveobject.h"
42
#if defined(HAVE_LIBSYSTEMD_LOGIN)
43
#include <systemd/sd-login.h>
47
* SECTION:udisksdaemonutil
49
* @short_description: Various utility routines
51
* Various utility routines.
55
* udisks_decode_udev_string:
56
* @str: An udev-encoded string or %NULL.
58
* Unescapes sequences like \x20 to " " and ensures the returned string is valid UTF-8.
60
* If the string is not valid UTF-8, try as hard as possible to convert to UTF-8.
62
* If %NULL is passed, then %NULL is returned.
64
* See udev_util_encode_string() in libudev/libudev-util.c in the udev
65
* tree for what kinds of strings can be used.
67
* Returns: A valid UTF-8 string that must be freed with g_free().
70
udisks_decode_udev_string (const gchar *str)
74
const gchar *end_valid;
83
s = g_string_new (NULL);
84
for (n = 0; str[n] != '\0'; n++)
90
if (str[n + 1] != 'x' || str[n + 2] == '\0' || str[n + 3] == '\0')
92
udisks_warning ("**** NOTE: malformed encoded string `%s'", str);
96
val = (g_ascii_xdigit_value (str[n + 2]) << 4) | g_ascii_xdigit_value (str[n + 3]);
98
g_string_append_c (s, val);
104
g_string_append_c (s, str[n]);
108
if (!g_utf8_validate (s->str, -1, &end_valid))
110
udisks_warning ("The string `%s' is not valid UTF-8. Invalid characters begins at `%s'", s->str, end_valid);
111
ret = g_strndup (s->str, end_valid - s->str);
112
g_string_free (s, TRUE);
116
ret = g_string_free (s, FALSE);
124
* udisks_safe_append_to_object_path:
125
* @str: A #GString to append to.
126
* @s: A UTF-8 string.
128
* Appends @s to @str in a way such that only characters that can be
129
* used in a D-Bus object path will be used. E.g. a character not in
130
* <literal>[A-Z][a-z][0-9]_</literal> will be escaped as _HEX where
131
* HEX is a two-digit hexadecimal number.
133
* Note that his mapping is not bijective - e.g. you cannot go back
134
* to the original string.
137
udisks_safe_append_to_object_path (GString *str,
141
for (n = 0; s[n] != '\0'; n++)
146
* Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_"
148
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_')
150
g_string_append_c (str, c);
154
/* Escape bytes not in [A-Z][a-z][0-9] as _<hex-with-two-digits> */
155
g_string_append_printf (str, "_%02x", c);
161
* udisks_daemon_util_block_get_size:
162
* @device: A #GUdevDevice for a top-level block device.
163
* @out_media_available: (out): Return location for whether media is available or %NULL.
164
* @out_media_change_detected: (out): Return location for whether media change is detected or %NULL.
166
* Gets the size of the @device top-level block device, checking for media in the process
168
* Returns: The size of @device or 0 if no media is available or if unknown.
171
udisks_daemon_util_block_get_size (GUdevDevice *device,
172
gboolean *out_media_available,
173
gboolean *out_media_change_detected)
175
gboolean media_available = FALSE;
176
gboolean media_change_detected = TRUE;
179
/* figuring out if media is available is a bit tricky */
180
if (g_udev_device_get_sysfs_attr_as_boolean (device, "removable"))
182
/* never try to open optical drives (might cause the door to close) or
183
* floppy drives (makes noise)
185
if (g_udev_device_get_property_as_boolean (device, "ID_DRIVE_FLOPPY"))
187
/* assume media available */
188
media_available = TRUE;
189
media_change_detected = FALSE;
191
else if (g_udev_device_get_property_as_boolean (device, "ID_CDROM"))
193
/* Rely on (careful) work already done by udev's cdrom_id prober */
194
if (g_udev_device_get_property_as_boolean (device, "ID_CDROM_MEDIA"))
195
media_available = TRUE;
200
/* For the general case, just rely on open(2) failing with
201
* ENOMEDIUM if no medium is inserted
203
fd = open (g_udev_device_get_device_file (device), O_RDONLY);
206
media_available = TRUE;
213
/* not removable, so media is implicitly available */
214
media_available = TRUE;
217
if (media_available && size == 0 && media_change_detected)
218
size = g_udev_device_get_sysfs_attr_as_uint64 (device, "size") * 512;
220
if (out_media_available != NULL)
221
*out_media_available = media_available;
223
if (out_media_change_detected != NULL)
224
*out_media_change_detected = media_change_detected;
231
* udisks_daemon_util_resolve_link:
233
* @name: Name of a symlink in @path.
235
* Resolves the symlink @path/@name.
237
* Returns: A canonicalized absolute pathname or %NULL if the symlink
238
* could not be resolved. Free with g_free().
241
udisks_daemon_util_resolve_link (const gchar *path,
245
gchar link_path[PATH_MAX];
246
gchar resolved_path[PATH_MAX];
252
full_path = g_build_filename (path, name, NULL);
254
num = readlink (full_path, link_path, sizeof(link_path) - 1);
259
link_path[num] = '\0';
261
absolute_path = g_build_filename (path, link_path, NULL);
262
if (realpath (absolute_path, resolved_path) != NULL)
266
g_free (absolute_path);
271
return g_strdup (resolved_path);
277
* udisks_daemon_util_resolve_links:
279
* @dir_name: Name of a directory in @path holding symlinks.
281
* Resolves all symlinks in @path/@dir_name. This can be used to
282
* easily walk e.g. holders or slaves of block devices.
284
* Returns: An array of canonicalized absolute pathnames. Free with g_strfreev().
287
udisks_daemon_util_resolve_links (const gchar *path,
288
const gchar *dir_name)
295
p = g_ptr_array_new ();
297
s = g_build_filename (path, dir_name, NULL);
298
dir = g_dir_open (s, 0, NULL);
301
while ((name = g_dir_read_name (dir)) != NULL)
304
resolved = udisks_daemon_util_resolve_link (s, name);
305
if (resolved != NULL)
306
g_ptr_array_add (p, resolved);
308
g_ptr_array_add (p, NULL);
315
return (gchar **) g_ptr_array_free (p, FALSE);
320
* udisks_daemon_util_setup_by_user:
321
* @daemon: A #UDisksDaemon.
322
* @object: The #GDBusObject that the call is on or %NULL.
323
* @user: The user in question.
325
* Checks whether the device represented by @object (if any) has been
328
* Returns: %TRUE if @object has been set-up by @user, %FALSE if not.
331
udisks_daemon_util_setup_by_user (UDisksDaemon *daemon,
332
UDisksObject *object,
336
UDisksBlock *block = NULL;
337
UDisksPartition *partition = NULL;
338
UDisksCleanup *cleanup;
340
UDisksObject *crypto_object;
344
cleanup = udisks_daemon_get_cleanup (daemon);
345
block = udisks_object_get_block (object);
348
partition = udisks_object_get_partition (object);
351
if (udisks_cleanup_has_loop (cleanup, udisks_block_get_device (block), &setup_by_user))
353
if (setup_by_user == user)
360
/* partition of a loop device */
361
if (partition != NULL)
363
UDisksObject *partition_object = NULL;
364
partition_object = udisks_daemon_find_object (daemon, udisks_partition_get_table (partition));
365
if (partition_object != NULL)
367
if (udisks_daemon_util_setup_by_user (daemon, partition_object, user))
370
g_object_unref (partition_object);
373
g_object_unref (partition_object);
378
crypto_object = udisks_daemon_find_object (daemon, udisks_block_get_crypto_backing_device (block));
379
if (crypto_object != NULL)
381
UDisksBlock *crypto_block;
382
crypto_block = udisks_object_peek_block (crypto_object);
383
if (udisks_cleanup_find_unlocked_luks (cleanup,
384
udisks_block_get_device_number (crypto_block),
387
if (setup_by_user == user)
390
g_object_unref (crypto_object);
394
g_object_unref (crypto_object);
398
g_clear_object (&partition);
399
g_clear_object (&block);
403
/* Need this until we can depend on a libpolkit with this bugfix
405
* http://cgit.freedesktop.org/polkit/commit/?h=wip/js-rule-files&id=224f7b892478302dccbe7e567b013d3c73d376fd
408
_safe_polkit_details_insert (PolkitDetails *details, const gchar *key, const gchar *value)
410
if (value != NULL && strlen (value) > 0)
411
polkit_details_insert (details, key, value);
415
_safe_polkit_details_insert_int (PolkitDetails *details, const gchar *key, gint value)
418
snprintf (buf, sizeof buf, "%d", value);
419
polkit_details_insert (details, key, buf);
423
_safe_polkit_details_insert_uint64 (PolkitDetails *details, const gchar *key, guint64 value)
426
snprintf (buf, sizeof buf, "0x%08llx", (unsigned long long int) value);
427
polkit_details_insert (details, key, buf);
431
check_authorization_no_polkit (UDisksDaemon *daemon,
432
UDisksObject *object,
433
const gchar *action_id,
435
const gchar *message,
436
GDBusMethodInvocation *invocation)
438
gboolean ret = FALSE;
439
uid_t caller_uid = -1;
440
GError *error = NULL;
442
if (!udisks_daemon_util_get_caller_uid_sync (daemon,
444
NULL, /* GCancellable* */
446
NULL, /* gid_t *out_gid */
447
NULL, /* gchar **out_user_name */
450
g_dbus_method_invocation_return_error (invocation,
453
"Error getting uid for caller with bus name %s: %s (%s, %d)",
454
g_dbus_method_invocation_get_sender (invocation),
455
error->message, g_quark_to_string (error->domain), error->code);
456
g_clear_error (&error);
460
/* only allow root */
467
g_dbus_method_invocation_return_error_literal (invocation,
469
UDISKS_ERROR_NOT_AUTHORIZED,
470
"Not authorized to perform operation (polkit authority not available and caller is not uid 0)");
478
* udisks_daemon_util_check_authorization_sync:
479
* @daemon: A #UDisksDaemon.
480
* @object: (allow-none): The #GDBusObject that the call is on or %NULL.
481
* @action_id: The action id to check for.
482
* @options: (allow-none): A #GVariant to check for the <quote>auth.no_user_interaction</quote> option or %NULL.
483
* @message: The message to convey (use N_).
484
* @invocation: The invocation to check for.
486
* Checks if the caller represented by @invocation is authorized for
487
* the action identified by @action_id, optionally displaying @message
488
* if authentication is needed. Additionally, if the caller is not
489
* authorized, the appropriate error is already returned to the caller
492
* The calling thread is blocked for the duration of the authorization
493
* check which could be a very long time since it may involve
494
* presenting an authentication dialog and having a human user use
495
* it. If <quote>auth.no_user_interaction</quote> in @options is %TRUE
496
* no authentication dialog will be presented and the check is not
497
* expected to take a long time.
499
* See <xref linkend="udisks-polkit-details"/> for the variables that
500
* can be used in @message but note that not all variables can be used
501
* in all checks. For example, any check involving a #UDisksDrive or a
502
* #UDisksBlock object can safely include the fragment
503
* <quote>$(drive)</quote> since it will always expand to the name of
504
* the drive, e.g. <quote>INTEL SSDSA2MH080G1GC (/dev/sda1)</quote> or
505
* the block device file e.g. <quote>/dev/vg_lucifer/lv_root</quote>
506
* or <quote>/dev/sda1</quote>. However this won't work for operations
507
* that isn't on a drive or block device, for example calls on the
508
* <link linkend="gdbus-interface-org-freedesktop-UDisks2-Manager.top_of_page">Manager</link>
511
* Returns: %TRUE if caller is authorized, %FALSE if not.
514
udisks_daemon_util_check_authorization_sync (UDisksDaemon *daemon,
515
UDisksObject *object,
516
const gchar *action_id,
518
const gchar *message,
519
GDBusMethodInvocation *invocation)
521
PolkitAuthority *authority = NULL;
522
PolkitSubject *subject = NULL;
523
PolkitDetails *details = NULL;
524
PolkitCheckAuthorizationFlags flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
525
PolkitAuthorizationResult *result = NULL;
526
GError *error = NULL;
527
gboolean ret = FALSE;
528
UDisksBlock *block = NULL;
529
UDisksDrive *drive = NULL;
530
UDisksPartition *partition = NULL;
531
UDisksObject *block_object = NULL;
532
UDisksObject *drive_object = NULL;
533
gboolean auth_no_user_interaction = FALSE;
534
const gchar *details_device = NULL;
535
gchar *details_drive = NULL;
537
authority = udisks_daemon_get_authority (daemon);
538
if (authority == NULL)
540
ret = check_authorization_no_polkit (daemon, object, action_id, options, message, invocation);
544
subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (invocation));
547
g_variant_lookup (options,
548
"auth.no_user_interaction",
550
&auth_no_user_interaction);
552
if (!auth_no_user_interaction)
553
flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION;
555
details = polkit_details_new ();
556
polkit_details_insert (details, "polkit.message", message);
557
polkit_details_insert (details, "polkit.gettext_domain", "udisks2");
559
/* Find drive associated with the block device, if any */
562
block = udisks_object_get_block (object);
565
block_object = g_object_ref (object);
566
drive_object = udisks_daemon_find_object (daemon, udisks_block_get_drive (block));
567
if (drive_object != NULL)
568
drive = udisks_object_get_drive (drive_object);
571
partition = udisks_object_get_partition (object);
575
details_device = udisks_block_get_preferred_device (block);
577
/* If we have a drive, use vendor/model in the message (in addition to Block:preferred-device) */
584
vendor = udisks_drive_get_vendor (drive);
585
model = udisks_drive_get_model (drive);
591
if (strlen (vendor) > 0 && strlen (model) > 0)
592
s = g_strdup_printf ("%s %s", vendor, model);
593
else if (strlen (vendor) > 0)
594
s = g_strdup (vendor);
596
s = g_strdup (model);
600
details_drive = g_strdup_printf ("%s (%s)", s, udisks_block_get_preferred_device (block));
609
_safe_polkit_details_insert (details, "drive.wwn", udisks_drive_get_wwn (drive));
610
_safe_polkit_details_insert (details, "drive.serial", udisks_drive_get_serial (drive));
611
_safe_polkit_details_insert (details, "drive.vendor", udisks_drive_get_vendor (drive));
612
_safe_polkit_details_insert (details, "drive.model", udisks_drive_get_model (drive));
613
_safe_polkit_details_insert (details, "drive.revision", udisks_drive_get_revision (drive));
614
if (udisks_drive_get_removable (drive))
615
polkit_details_insert (details, "drive.removable", "true");
620
_safe_polkit_details_insert (details, "id.type", udisks_block_get_id_type (block));
621
_safe_polkit_details_insert (details, "id.usage", udisks_block_get_id_usage (block));
622
_safe_polkit_details_insert (details, "id.version", udisks_block_get_id_version (block));
623
_safe_polkit_details_insert (details, "id.label", udisks_block_get_id_label (block));
624
_safe_polkit_details_insert (details, "id.uuid", udisks_block_get_id_uuid (block));
627
if (partition != NULL)
629
_safe_polkit_details_insert_int (details, "partition.number", udisks_partition_get_number (partition));
630
_safe_polkit_details_insert (details, "partition.type", udisks_partition_get_type_ (partition));
631
_safe_polkit_details_insert_uint64 (details, "partition.flags", udisks_partition_get_flags (partition));
632
_safe_polkit_details_insert (details, "partition.name", udisks_partition_get_name (partition));
633
_safe_polkit_details_insert (details, "partition.uuid", udisks_partition_get_uuid (partition));
636
/* Fall back to Block:preferred-device */
637
if (details_drive == NULL && block != NULL)
638
details_drive = udisks_block_dup_preferred_device (block);
640
if (details_device != NULL)
641
polkit_details_insert (details, "device", details_device);
642
if (details_drive != NULL)
643
polkit_details_insert (details, "drive", details_drive);
646
result = polkit_authority_check_authorization_sync (authority,
651
NULL, /* GCancellable* */
655
g_dbus_method_invocation_return_error (invocation,
658
"Error checking authorization: %s (%s, %d)",
660
g_quark_to_string (error->domain),
662
g_error_free (error);
665
if (!polkit_authorization_result_get_is_authorized (result))
667
if (polkit_authorization_result_get_dismissed (result))
668
g_dbus_method_invocation_return_error_literal (invocation,
670
UDISKS_ERROR_NOT_AUTHORIZED_DISMISSED,
671
"The authentication dialog was dismissed");
673
g_dbus_method_invocation_return_error_literal (invocation,
675
polkit_authorization_result_get_is_challenge (result) ?
676
UDISKS_ERROR_NOT_AUTHORIZED_CAN_OBTAIN :
677
UDISKS_ERROR_NOT_AUTHORIZED,
678
"Not authorized to perform operation");
685
g_free (details_drive);
686
g_clear_object (&block_object);
687
g_clear_object (&drive_object);
688
g_clear_object (&block);
689
g_clear_object (&partition);
690
g_clear_object (&drive);
691
g_clear_object (&subject);
692
g_clear_object (&details);
693
g_clear_object (&result);
697
/* ---------------------------------------------------------------------------------------------------- */
700
* udisks_daemon_util_get_caller_uid_sync:
701
* @daemon: A #UDisksDaemon.
702
* @invocation: A #GDBusMethodInvocation.
703
* @cancellable: (allow-none): A #GCancellable or %NULL.
704
* @out_uid: (out): Return location for resolved uid or %NULL.
705
* @out_gid: (out) (allow-none): Return location for resolved gid or %NULL.
706
* @out_user_name: (out) (allow-none): Return location for resolved user name or %NULL.
707
* @error: Return location for error.
709
* Gets the UNIX user id (and possibly group id and user name) of the
710
* peer represented by @invocation.
712
* Returns: %TRUE if the user id (and possibly group id) was obtained, %FALSE otherwise
715
udisks_daemon_util_get_caller_uid_sync (UDisksDaemon *daemon,
716
GDBusMethodInvocation *invocation,
717
GCancellable *cancellable,
720
gchar **out_user_name,
729
/* TODO: cache this on @daemon */
733
caller = g_dbus_method_invocation_get_sender (invocation);
736
value = g_dbus_connection_call_sync (g_dbus_method_invocation_get_connection (invocation),
737
"org.freedesktop.DBus", /* bus name */
738
"/org/freedesktop/DBus", /* object path */
739
"org.freedesktop.DBus", /* interface */
740
"GetConnectionUnixUser", /* method */
741
g_variant_new ("(s)", caller),
742
G_VARIANT_TYPE ("(u)"),
743
G_DBUS_CALL_FLAGS_NONE,
744
-1, /* timeout_msec */
752
"Error determining uid of caller %s: %s (%s, %d)",
754
local_error->message,
755
g_quark_to_string (local_error->domain),
757
g_error_free (local_error);
761
G_STATIC_ASSERT (sizeof (uid_t) == sizeof (guint32));
762
g_variant_get (value, "(u)", &uid);
766
if (out_gid != NULL || out_user_name != NULL)
768
struct passwd pwstruct;
770
static struct passwd *pw;
773
rc = getpwuid_r (uid, &pwstruct, pwbuf, sizeof pwbuf, &pw);
774
if (rc == 0 && pw == NULL)
779
"User with uid %d does not exist", (gint) uid);
786
"Error looking up passwd struct for uid %d: %m", (gint) uid);
790
*out_gid = pw->pw_gid;
791
if (out_user_name != NULL)
792
*out_user_name = g_strdup (pwstruct.pw_name);
801
/* ---------------------------------------------------------------------------------------------------- */
804
* udisks_daemon_util_get_caller_pid_sync:
805
* @daemon: A #UDisksDaemon.
806
* @invocation: A #GDBusMethodInvocation.
807
* @cancellable: (allow-none): A #GCancellable or %NULL.
808
* @out_pid: (out): Return location for resolved pid or %NULL.
809
* @error: Return location for error.
811
* Gets the UNIX process id of the peer represented by @invocation.
813
* Returns: %TRUE if the process id was obtained, %FALSE otherwise
816
udisks_daemon_util_get_caller_pid_sync (UDisksDaemon *daemon,
817
GDBusMethodInvocation *invocation,
818
GCancellable *cancellable,
828
/* TODO: cache this on @daemon */
832
caller = g_dbus_method_invocation_get_sender (invocation);
835
value = g_dbus_connection_call_sync (g_dbus_method_invocation_get_connection (invocation),
836
"org.freedesktop.DBus", /* bus name */
837
"/org/freedesktop/DBus", /* object path */
838
"org.freedesktop.DBus", /* interface */
839
"GetConnectionUnixProcessID", /* method */
840
g_variant_new ("(s)", caller),
841
G_VARIANT_TYPE ("(u)"),
842
G_DBUS_CALL_FLAGS_NONE,
843
-1, /* timeout_msec */
851
"Error determining uid of caller %s: %s (%s, %d)",
853
local_error->message,
854
g_quark_to_string (local_error->domain),
856
g_error_free (local_error);
860
G_STATIC_ASSERT (sizeof (uid_t) == sizeof (guint32));
861
g_variant_get (value, "(u)", &pid);
871
/* ---------------------------------------------------------------------------------------------------- */
874
* udisks_daemon_util_dup_object:
875
* @interface_: (type GDBusInterface): A #GDBusInterface<!-- -->-derived instance.
876
* @error: %NULL, or an unset #GError to set if the return value is %NULL.
878
* Gets the enclosing #UDisksObject for @interface, if any.
880
* Returns: (transfer full) (type UDisksObject): Either %NULL or a
881
* #UDisksObject<!-- -->-derived instance that must be released with
885
udisks_daemon_util_dup_object (gpointer interface_,
890
g_return_val_if_fail (G_IS_DBUS_INTERFACE (interface_), NULL);
891
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
893
ret = g_dbus_interface_dup_object (interface_);
899
"No enclosing object for interface");
906
escaper (GString *s, const gchar *str)
909
for (p = str; *p != '\0'; p++)
915
g_string_append (s, "\\\"");
919
g_string_append (s, "\\\\");
923
g_string_append_c (s, c);
930
* udisks_daemon_util_escape_and_quote:
931
* @str: The string to escape.
933
* Like udisks_daemon_util_escape() but also wraps the result in
936
* Returns: The double-quoted and escaped string. Free with g_free().
939
udisks_daemon_util_escape_and_quote (const gchar *str)
943
g_return_val_if_fail (str != NULL, NULL);
945
s = g_string_new ("\"");
947
g_string_append_c (s, '"');
949
return g_string_free (s, FALSE);
953
* udisks_daemon_util_escape:
954
* @str: The string to escape.
956
* Escapes double-quotes (") and back-slashes (\) in a string
957
* using back-slash (\).
959
* Returns: The escaped string. Free with g_free().
962
udisks_daemon_util_escape (const gchar *str)
966
g_return_val_if_fail (str != NULL, NULL);
968
s = g_string_new (NULL);
971
return g_string_free (s, FALSE);
975
* udisks_daemon_util_on_other_seat:
976
* @daemon: A #UDisksDaemon.
977
* @object: The #GDBusObject that the call is on or %NULL.
978
* @process: The process to check for.
980
* Checks whether the device represented by @object (if any) is plugged into
981
* a seat where the caller represented by @process is logged in.
983
* This works if @object is a drive or a block object.
985
* Returns: %TRUE if @object and @process is on the same seat, %FALSE otherwise.
988
udisks_daemon_util_on_same_seat (UDisksDaemon *daemon,
989
UDisksObject *object,
992
#if !defined(HAVE_LIBSYSTEMD_LOGIN)
993
/* if we don't have systemd, assume it's always the same seat */
996
gboolean ret = FALSE;
997
char *session = NULL;
999
const gchar *drive_seat;
1000
UDisksObject *drive_object = NULL;
1001
UDisksDrive *drive = NULL;
1003
if (UDISKS_IS_LINUX_BLOCK_OBJECT (object))
1005
UDisksLinuxBlockObject *linux_block_object;
1007
linux_block_object = UDISKS_LINUX_BLOCK_OBJECT (object);
1008
block = udisks_object_get_block (UDISKS_OBJECT (linux_block_object));
1011
drive_object = udisks_daemon_find_object (daemon, udisks_block_get_drive (block));
1012
g_object_unref (block);
1015
else if (UDISKS_IS_LINUX_DRIVE_OBJECT (object))
1017
drive_object = g_object_ref (object);
1020
if (drive_object == NULL)
1023
drive = udisks_object_get_drive (UDISKS_OBJECT (drive_object));
1027
/* It's not unexpected to not find a session, nor a seat associated with @process */
1028
if (sd_pid_get_session (process, &session) == 0)
1029
sd_session_get_seat (session, &seat);
1031
/* If we don't know the seat of the caller, we assume the device is always on another seat */
1035
drive_seat = udisks_drive_get_seat (drive);
1036
if (g_strcmp0 (seat, drive_seat) == 0)
1045
g_clear_object (&drive_object);
1046
g_clear_object (&drive);
1048
#endif /* HAVE_LIBSYSTEMD_LOGIN */