~behda/+junk/udisks2.original

« back to all changes in this revision

Viewing changes to src/udiskslinuxswapspace.c

  • Committer: behda
  • Date: 2014-05-24 15:15:11 UTC
  • Revision ID: pauvitk@gmail.com-20140524151511-3vtr0uubjewx3z2j
Initial commit of source code and Debian packaging.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
 
2
 *
 
3
 * Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com>
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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
 
18
 *
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
#include <glib/gi18n-lib.h>
 
23
 
 
24
#include <sys/types.h>
 
25
#include <pwd.h>
 
26
#include <grp.h>
 
27
#include <string.h>
 
28
#include <stdlib.h>
 
29
 
 
30
#include <glib/gstdio.h>
 
31
 
 
32
#include "udiskslogging.h"
 
33
#include "udiskslinuxswapspace.h"
 
34
#include "udiskslinuxblockobject.h"
 
35
#include "udisksdaemon.h"
 
36
#include "udisksdaemonutil.h"
 
37
#include "udisksmountmonitor.h"
 
38
#include "udiskslinuxdevice.h"
 
39
 
 
40
/**
 
41
 * SECTION:udiskslinuxswapspace
 
42
 * @title: UDisksLinuxSwapspace
 
43
 * @short_description: Linux implementation of #UDisksSwapspace
 
44
 *
 
45
 * This type provides an implementation of the #UDisksSwapspace interface
 
46
 * on Linux.
 
47
 */
 
48
 
 
49
typedef struct _UDisksLinuxSwapspaceClass   UDisksLinuxSwapspaceClass;
 
50
 
 
51
/**
 
52
 * UDisksLinuxSwapspace:
 
53
 *
 
54
 * The #UDisksLinuxSwapspace structure contains only private data and should
 
55
 * only be accessed using the provided API.
 
56
 */
 
57
struct _UDisksLinuxSwapspace
 
58
{
 
59
  UDisksSwapspaceSkeleton parent_instance;
 
60
};
 
61
 
 
62
struct _UDisksLinuxSwapspaceClass
 
63
{
 
64
  UDisksSwapspaceSkeletonClass parent_class;
 
65
};
 
66
 
 
67
static void swapspace_iface_init (UDisksSwapspaceIface *iface);
 
68
 
 
69
G_DEFINE_TYPE_WITH_CODE (UDisksLinuxSwapspace, udisks_linux_swapspace, UDISKS_TYPE_SWAPSPACE_SKELETON,
 
70
                         G_IMPLEMENT_INTERFACE (UDISKS_TYPE_SWAPSPACE, swapspace_iface_init));
 
71
 
 
72
/* ---------------------------------------------------------------------------------------------------- */
 
73
 
 
74
static void
 
75
udisks_linux_swapspace_init (UDisksLinuxSwapspace *swapspace)
 
76
{
 
77
  g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (swapspace),
 
78
                                       G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
 
79
}
 
80
 
 
81
static void
 
82
udisks_linux_swapspace_class_init (UDisksLinuxSwapspaceClass *klass)
 
83
{
 
84
}
 
85
 
 
86
/**
 
87
 * udisks_linux_swapspace_new:
 
88
 *
 
89
 * Creates a new #UDisksLinuxSwapspace instance.
 
90
 *
 
91
 * Returns: A new #UDisksLinuxSwapspace. Free with g_object_unref().
 
92
 */
 
93
UDisksSwapspace *
 
94
udisks_linux_swapspace_new (void)
 
95
{
 
96
  return UDISKS_SWAPSPACE (g_object_new (UDISKS_TYPE_LINUX_SWAPSPACE,
 
97
                                          NULL));
 
98
}
 
99
 
 
100
/* ---------------------------------------------------------------------------------------------------- */
 
101
 
 
102
/**
 
103
 * udisks_linux_swapspace_update:
 
104
 * @swapspace: A #UDisksLinuxSwapspace.
 
105
 * @object: The enclosing #UDisksLinuxBlockObject instance.
 
106
 *
 
107
 * Updates the interface.
 
108
 */
 
109
void
 
110
udisks_linux_swapspace_update (UDisksLinuxSwapspace   *swapspace,
 
111
                               UDisksLinuxBlockObject *object)
 
112
{
 
113
  UDisksMountMonitor *mount_monitor;
 
114
  UDisksLinuxDevice *device;
 
115
  UDisksMountType mount_type;
 
116
  gboolean active;
 
117
 
 
118
  mount_monitor = udisks_daemon_get_mount_monitor (udisks_linux_block_object_get_daemon (object));
 
119
  device = udisks_linux_block_object_get_device (object);
 
120
 
 
121
  active = FALSE;
 
122
  if (udisks_mount_monitor_is_dev_in_use (mount_monitor, g_udev_device_get_device_number (device->udev_device), &mount_type) &&
 
123
      mount_type == UDISKS_MOUNT_TYPE_SWAP)
 
124
    active = TRUE;
 
125
  udisks_swapspace_set_active (UDISKS_SWAPSPACE (swapspace), active);
 
126
 
 
127
  g_object_unref (device);
 
128
}
 
129
 
 
130
/* ---------------------------------------------------------------------------------------------------- */
 
131
 
 
132
 
 
133
static void
 
134
swapspace_start_on_job_completed (UDisksJob   *job,
 
135
                                  gboolean     success,
 
136
                                  const gchar *message,
 
137
                                  gpointer     user_data)
 
138
{
 
139
  GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
 
140
  UDisksSwapspace *swapspace;
 
141
  swapspace = UDISKS_SWAPSPACE (g_dbus_method_invocation_get_user_data (invocation));
 
142
  if (success)
 
143
    udisks_swapspace_complete_start (swapspace, invocation);
 
144
  else
 
145
    g_dbus_method_invocation_return_error (invocation,
 
146
                                           UDISKS_ERROR,
 
147
                                           UDISKS_ERROR_FAILED,
 
148
                                           "Error activating swap: %s",
 
149
                                           message);
 
150
}
 
151
 
 
152
static gboolean
 
153
handle_start (UDisksSwapspace        *swapspace,
 
154
              GDBusMethodInvocation  *invocation,
 
155
              GVariant               *options)
 
156
{
 
157
  UDisksObject *object;
 
158
  UDisksDaemon *daemon;
 
159
  UDisksBlock *block;
 
160
  UDisksBaseJob *job;
 
161
  GError *error;
 
162
  gchar *escaped_device = NULL;
 
163
  uid_t caller_uid;
 
164
  gid_t caller_gid;
 
165
 
 
166
  error = NULL;
 
167
  object = udisks_daemon_util_dup_object (swapspace, &error);
 
168
  if (object == NULL)
 
169
    {
 
170
      g_dbus_method_invocation_take_error (invocation, error);
 
171
      goto out;
 
172
    }
 
173
 
 
174
  daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object));
 
175
  block = udisks_object_peek_block (object);
 
176
 
 
177
  error = NULL;
 
178
  if (!udisks_daemon_util_get_caller_uid_sync (daemon,
 
179
                                               invocation,
 
180
                                               NULL /* GCancellable */,
 
181
                                               &caller_uid,
 
182
                                               &caller_gid,
 
183
                                               NULL,
 
184
                                               &error))
 
185
    {
 
186
      g_dbus_method_invocation_return_gerror (invocation, error);
 
187
      g_error_free (error);
 
188
      goto out;
 
189
    }
 
190
 
 
191
  if (!udisks_daemon_util_check_authorization_sync (daemon,
 
192
                                                    object,
 
193
                                                    "org.freedesktop.udisks2.manage-swapspace",
 
194
                                                    options,
 
195
                                                    /* Translators: Shown in authentication dialog when the user
 
196
                                                     * requests activating a swap device.
 
197
                                                     *
 
198
                                                     * Do not translate $(drive), it's a placeholder and
 
199
                                                     * will be replaced by the name of the drive/device in question
 
200
                                                     */
 
201
                                                    N_("Authentication is required to activate swapspace on $(drive)"),
 
202
                                                    invocation))
 
203
    goto out;
 
204
 
 
205
  escaped_device = udisks_daemon_util_escape_and_quote (udisks_block_get_device (block));
 
206
 
 
207
  job = udisks_daemon_launch_spawned_job (daemon,
 
208
                                          object,
 
209
                                          "swapspace-start", caller_uid,
 
210
                                          NULL, /* cancellable */
 
211
                                          0,    /* uid_t run_as_uid */
 
212
                                          0,    /* uid_t run_as_euid */
 
213
                                          NULL, /* input_string */
 
214
                                          "swapon %s",
 
215
                                          escaped_device);
 
216
  g_signal_connect (job,
 
217
                    "completed",
 
218
                    G_CALLBACK (swapspace_start_on_job_completed),
 
219
                    invocation);
 
220
 
 
221
 out:
 
222
  g_free (escaped_device);
 
223
  g_clear_object (&object);
 
224
  return TRUE;
 
225
}
 
226
 
 
227
static void
 
228
swapspace_stop_on_job_completed (UDisksJob   *job,
 
229
                                 gboolean     success,
 
230
                                 const gchar *message,
 
231
                                  gpointer     user_data)
 
232
{
 
233
  GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
 
234
  UDisksSwapspace *swapspace;
 
235
  swapspace = UDISKS_SWAPSPACE (g_dbus_method_invocation_get_user_data (invocation));
 
236
  if (success)
 
237
    udisks_swapspace_complete_start (swapspace, invocation);
 
238
  else
 
239
    g_dbus_method_invocation_return_error (invocation,
 
240
                                           UDISKS_ERROR,
 
241
                                           UDISKS_ERROR_FAILED,
 
242
                                           "Error deactivating swap: %s",
 
243
                                           message);
 
244
}
 
245
 
 
246
static gboolean
 
247
handle_stop (UDisksSwapspace        *swapspace,
 
248
             GDBusMethodInvocation  *invocation,
 
249
             GVariant               *options)
 
250
{
 
251
  UDisksObject *object;
 
252
  UDisksDaemon *daemon;
 
253
  UDisksBlock *block;
 
254
  UDisksBaseJob *job;
 
255
  uid_t caller_uid;
 
256
  gid_t caller_gid;
 
257
  gchar *escaped_device = NULL;
 
258
  GError *error = NULL;
 
259
 
 
260
  object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (swapspace)));
 
261
  daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object));
 
262
  block = udisks_object_peek_block (object);
 
263
 
 
264
  error = NULL;
 
265
  if (!udisks_daemon_util_get_caller_uid_sync (daemon,
 
266
                                               invocation,
 
267
                                               NULL /* GCancellable */,
 
268
                                               &caller_uid,
 
269
                                               &caller_gid,
 
270
                                               NULL,
 
271
                                               &error))
 
272
    {
 
273
      g_dbus_method_invocation_return_gerror (invocation, error);
 
274
      g_error_free (error);
 
275
      goto out;
 
276
    }
 
277
 
 
278
  /* Now, check that the user is actually authorized to stop the swap space.
 
279
   *
 
280
   * TODO: want nicer authentication message + special treatment if the
 
281
   * uid that locked the device (e.g. w/o -others).
 
282
   */
 
283
  if (!udisks_daemon_util_check_authorization_sync (daemon,
 
284
                                                    object,
 
285
                                                    "org.freedesktop.udisks2.manage-swapspace",
 
286
                                                    options,
 
287
                                                    /* Translators: Shown in authentication dialog when the user
 
288
                                                     * requests deactivating a swap device.
 
289
                                                     *
 
290
                                                     * Do not translate $(drive), it's a placeholder and
 
291
                                                     * will be replaced by the name of the drive/device in question
 
292
                                                     */
 
293
                                                    N_("Authentication is required to deactivate swapspace on $(drive)"),
 
294
                                                    invocation))
 
295
    goto out;
 
296
 
 
297
  escaped_device = udisks_daemon_util_escape_and_quote (udisks_block_get_device (block));
 
298
 
 
299
  job = udisks_daemon_launch_spawned_job (daemon,
 
300
                                          object,
 
301
                                          "swapspace-stop", caller_uid,
 
302
                                          NULL, /* cancellable */
 
303
                                          0,    /* uid_t run_as_uid */
 
304
                                          0,    /* uid_t run_as_euid */
 
305
                                          NULL, /* input_string */
 
306
                                          "swapoff %s",
 
307
                                          escaped_device);
 
308
  g_signal_connect (job,
 
309
                    "completed",
 
310
                    G_CALLBACK (swapspace_stop_on_job_completed),
 
311
                    invocation);
 
312
 
 
313
 out:
 
314
  g_free (escaped_device);
 
315
  return TRUE;
 
316
}
 
317
 
 
318
/* ---------------------------------------------------------------------------------------------------- */
 
319
 
 
320
static void
 
321
swapspace_iface_init (UDisksSwapspaceIface *iface)
 
322
{
 
323
  iface->handle_start  = handle_start;
 
324
  iface->handle_stop   = handle_stop;
 
325
}