~behda/+junk/udisks2.original

« back to all changes in this revision

Viewing changes to udisks/udisksclient.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) 2011 David Zeuthen <zeuthen@gmail.com>
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library 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 GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General
 
16
 * Public License along with this library; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
#include <glib/gi18n-lib.h>
 
23
 
 
24
#include "udisksclient.h"
 
25
#include "udiskserror.h"
 
26
#include "udisks-generated.h"
 
27
#include "udisksobjectinfo.h"
 
28
 
 
29
/* For __GNUC_PREREQ usage below */
 
30
#ifdef __GNUC__
 
31
# include <features.h>
 
32
#endif
 
33
 
 
34
/**
 
35
 * SECTION:udisksclient
 
36
 * @title: UDisksClient
 
37
 * @short_description: Utility routines for accessing the UDisks service
 
38
 *
 
39
 * #UDisksClient is used for accessing the UDisks service from a
 
40
 * client program.
 
41
 */
 
42
 
 
43
G_LOCK_DEFINE_STATIC (init_lock);
 
44
 
 
45
/**
 
46
 * UDisksClient:
 
47
 *
 
48
 * The #UDisksClient structure contains only private data and should
 
49
 * only be accessed using the provided API.
 
50
 */
 
51
struct _UDisksClient
 
52
{
 
53
  GObject parent_instance;
 
54
 
 
55
  gboolean is_initialized;
 
56
  GError *initialization_error;
 
57
 
 
58
  GDBusObjectManager *object_manager;
 
59
 
 
60
  GMainContext *context;
 
61
 
 
62
  GSource *changed_timeout_source;
 
63
};
 
64
 
 
65
typedef struct
 
66
{
 
67
  GObjectClass parent_class;
 
68
} UDisksClientClass;
 
69
 
 
70
enum
 
71
{
 
72
  PROP_0,
 
73
  PROP_OBJECT_MANAGER,
 
74
  PROP_MANAGER
 
75
};
 
76
 
 
77
enum
 
78
{
 
79
  CHANGED_SIGNAL,
 
80
  LAST_SIGNAL
 
81
};
 
82
 
 
83
static guint signals[LAST_SIGNAL] = { 0 };
 
84
 
 
85
static void initable_iface_init       (GInitableIface      *initable_iface);
 
86
static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface);
 
87
 
 
88
static void on_object_added (GDBusObjectManager  *manager,
 
89
                             GDBusObject         *object,
 
90
                             gpointer             user_data);
 
91
 
 
92
static void on_object_removed (GDBusObjectManager  *manager,
 
93
                               GDBusObject         *object,
 
94
                               gpointer             user_data);
 
95
 
 
96
static void on_interface_added (GDBusObjectManager  *manager,
 
97
                                GDBusObject         *object,
 
98
                                GDBusInterface      *interface,
 
99
                                gpointer             user_data);
 
100
 
 
101
static void on_interface_removed (GDBusObjectManager  *manager,
 
102
                                  GDBusObject         *object,
 
103
                                  GDBusInterface      *interface,
 
104
                                  gpointer             user_data);
 
105
 
 
106
static void on_interface_proxy_properties_changed (GDBusObjectManagerClient   *manager,
 
107
                                                   GDBusObjectProxy           *object_proxy,
 
108
                                                   GDBusProxy                 *interface_proxy,
 
109
                                                   GVariant                   *changed_properties,
 
110
                                                   const gchar *const         *invalidated_properties,
 
111
                                                   gpointer                    user_data);
 
112
 
 
113
static void maybe_emit_changed_now (UDisksClient *client);
 
114
 
 
115
static void init_interface_proxy (UDisksClient *client,
 
116
                                  GDBusProxy   *proxy);
 
117
 
 
118
static UDisksPartitionTypeInfo *udisks_partition_type_info_new (void);
 
119
 
 
120
G_DEFINE_TYPE_WITH_CODE (UDisksClient, udisks_client, G_TYPE_OBJECT,
 
121
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
 
122
                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
 
123
                         );
 
124
 
 
125
static void
 
126
udisks_client_finalize (GObject *object)
 
127
{
 
128
  UDisksClient *client = UDISKS_CLIENT (object);
 
129
 
 
130
  if (client->changed_timeout_source != NULL)
 
131
    g_source_destroy (client->changed_timeout_source);
 
132
 
 
133
  if (client->initialization_error != NULL)
 
134
    g_error_free (client->initialization_error);
 
135
 
 
136
  g_signal_handlers_disconnect_by_func (client->object_manager,
 
137
                                        G_CALLBACK (on_object_added),
 
138
                                        client);
 
139
  g_signal_handlers_disconnect_by_func (client->object_manager,
 
140
                                        G_CALLBACK (on_object_removed),
 
141
                                        client);
 
142
  g_signal_handlers_disconnect_by_func (client->object_manager,
 
143
                                        G_CALLBACK (on_interface_added),
 
144
                                        client);
 
145
  g_signal_handlers_disconnect_by_func (client->object_manager,
 
146
                                        G_CALLBACK (on_interface_removed),
 
147
                                        client);
 
148
  g_signal_handlers_disconnect_by_func (client->object_manager,
 
149
                                        G_CALLBACK (on_interface_proxy_properties_changed),
 
150
                                        client);
 
151
  g_object_unref (client->object_manager);
 
152
 
 
153
  if (client->context != NULL)
 
154
    g_main_context_unref (client->context);
 
155
 
 
156
  G_OBJECT_CLASS (udisks_client_parent_class)->finalize (object);
 
157
}
 
158
 
 
159
static void
 
160
udisks_client_init (UDisksClient *client)
 
161
{
 
162
  static volatile GQuark udisks_error_domain = 0;
 
163
  /* this will force associating errors in the UDISKS_ERROR error
 
164
   * domain with org.freedesktop.UDisks2.Error.* errors via
 
165
   * g_dbus_error_register_error_domain().
 
166
   */
 
167
  udisks_error_domain = UDISKS_ERROR;
 
168
  udisks_error_domain; /* shut up -Wunused-but-set-variable */
 
169
}
 
170
 
 
171
static void
 
172
udisks_client_get_property (GObject    *object,
 
173
                            guint       prop_id,
 
174
                            GValue     *value,
 
175
                            GParamSpec *pspec)
 
176
{
 
177
  UDisksClient *client = UDISKS_CLIENT (object);
 
178
 
 
179
  switch (prop_id)
 
180
    {
 
181
    case PROP_OBJECT_MANAGER:
 
182
      g_value_set_object (value, udisks_client_get_object_manager (client));
 
183
      break;
 
184
 
 
185
    case PROP_MANAGER:
 
186
      g_value_set_object (value, udisks_client_get_manager (client));
 
187
      break;
 
188
 
 
189
    default:
 
190
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
191
      break;
 
192
    }
 
193
}
 
194
 
 
195
static void
 
196
udisks_client_class_init (UDisksClientClass *klass)
 
197
{
 
198
  GObjectClass *gobject_class;
 
199
 
 
200
  gobject_class = G_OBJECT_CLASS (klass);
 
201
  gobject_class->finalize     = udisks_client_finalize;
 
202
  gobject_class->get_property = udisks_client_get_property;
 
203
 
 
204
  /**
 
205
   * UDisksClient:object-manager:
 
206
   *
 
207
   * The #GDBusObjectManager used by the #UDisksClient instance.
 
208
   */
 
209
  g_object_class_install_property (gobject_class,
 
210
                                   PROP_OBJECT_MANAGER,
 
211
                                   g_param_spec_object ("object-manager",
 
212
                                                        "Object Manager",
 
213
                                                        "The GDBusObjectManager used by the UDisksClient",
 
214
                                                        G_TYPE_DBUS_OBJECT_MANAGER,
 
215
                                                        G_PARAM_READABLE |
 
216
                                                        G_PARAM_STATIC_STRINGS));
 
217
 
 
218
  /**
 
219
   * UDisksClient:manager:
 
220
   *
 
221
   * The #UDisksManager interface on the well-known
 
222
   * <literal>/org/freedesktop/UDisks2/Manager</literal> object
 
223
   */
 
224
  g_object_class_install_property (gobject_class,
 
225
                                   PROP_MANAGER,
 
226
                                   g_param_spec_object ("manager",
 
227
                                                        "Manager",
 
228
                                                        "The UDisksManager",
 
229
                                                        UDISKS_TYPE_MANAGER,
 
230
                                                        G_PARAM_READABLE |
 
231
                                                        G_PARAM_STATIC_STRINGS));
 
232
 
 
233
  /**
 
234
   * UDisksClient::changed:
 
235
   * @client: A #UDisksClient.
 
236
   *
 
237
   * This signal is emitted either when an object or interface is
 
238
   * added or removed a when property has changed. Additionally,
 
239
   * multiple received signals are coalesced into a single signal that
 
240
   * is rate-limited to fire at most every 100ms.
 
241
   *
 
242
   * Note that calling udisks_client_settle() will cause this signal
 
243
   * to fire if any changes are outstanding.
 
244
   *
 
245
   * For greater detail, connect to the
 
246
   * #GDBusObjectManager::object-added,
 
247
   * #GDBusObjectManager::object-removed,
 
248
   * #GDBusObjectManager::interface-added,
 
249
   * #GDBusObjectManager::interface-removed,
 
250
   * #GDBusObjectManagerClient::interface-proxy-properties-changed and
 
251
   * signals on the #UDisksClient:object-manager object.
 
252
   */
 
253
  signals[CHANGED_SIGNAL] = g_signal_new ("changed",
 
254
                                          G_OBJECT_CLASS_TYPE (klass),
 
255
                                          G_SIGNAL_RUN_LAST,
 
256
                                          0, /* G_STRUCT_OFFSET */
 
257
                                          NULL, /* accu */
 
258
                                          NULL, /* accu data */
 
259
                                          g_cclosure_marshal_generic,
 
260
                                          G_TYPE_NONE,
 
261
                                          0);
 
262
 
 
263
}
 
264
 
 
265
/**
 
266
 * udisks_client_new:
 
267
 * @cancellable: A #GCancellable or %NULL.
 
268
 * @callback: Function that will be called when the result is ready.
 
269
 * @user_data: Data to pass to @callback.
 
270
 *
 
271
 * Asynchronously gets a #UDisksClient. When the operation is
 
272
 * finished, @callback will be invoked in the <link
 
273
 * linkend="g-main-context-push-thread-default">thread-default main
 
274
 * loop</link> of the thread you are calling this method from.
 
275
 */
 
276
void
 
277
udisks_client_new (GCancellable        *cancellable,
 
278
                   GAsyncReadyCallback  callback,
 
279
                   gpointer             user_data)
 
280
{
 
281
  g_async_initable_new_async (UDISKS_TYPE_CLIENT,
 
282
                              G_PRIORITY_DEFAULT,
 
283
                              cancellable,
 
284
                              callback,
 
285
                              user_data,
 
286
                              NULL);
 
287
}
 
288
 
 
289
/**
 
290
 * udisks_client_new_finish:
 
291
 * @res: A #GAsyncResult.
 
292
 * @error: Return location for error or %NULL.
 
293
 *
 
294
 * Finishes an operation started with udisks_client_new().
 
295
 *
 
296
 * Returns: A #UDisksClient or %NULL if @error is set. Free with
 
297
 * g_object_unref() when done with it.
 
298
 */
 
299
UDisksClient *
 
300
udisks_client_new_finish (GAsyncResult        *res,
 
301
                          GError             **error)
 
302
{
 
303
  GObject *ret;
 
304
  GObject *source_object;
 
305
  source_object = g_async_result_get_source_object (res);
 
306
  ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
 
307
  g_object_unref (source_object);
 
308
  if (ret != NULL)
 
309
    return UDISKS_CLIENT (ret);
 
310
  else
 
311
    return NULL;
 
312
}
 
313
 
 
314
/**
 
315
 * udisks_client_new_sync:
 
316
 * @cancellable: (allow-none): A #GCancellable or %NULL.
 
317
 * @error: (allow-none): Return location for error or %NULL.
 
318
 *
 
319
 * Synchronously gets a #UDisksClient for the local system.
 
320
 *
 
321
 * Returns: A #UDisksClient or %NULL if @error is set. Free with
 
322
 * g_object_unref() when done with it.
 
323
 */
 
324
UDisksClient *
 
325
udisks_client_new_sync (GCancellable  *cancellable,
 
326
                        GError       **error)
 
327
{
 
328
  GInitable *ret;
 
329
  ret = g_initable_new (UDISKS_TYPE_CLIENT,
 
330
                        cancellable,
 
331
                        error,
 
332
                        NULL);
 
333
  if (ret != NULL)
 
334
    return UDISKS_CLIENT (ret);
 
335
  else
 
336
    return NULL;
 
337
}
 
338
 
 
339
/* ---------------------------------------------------------------------------------------------------- */
 
340
 
 
341
static gboolean
 
342
initable_init (GInitable     *initable,
 
343
               GCancellable  *cancellable,
 
344
               GError       **error)
 
345
{
 
346
  UDisksClient *client = UDISKS_CLIENT (initable);
 
347
  gboolean ret;
 
348
  GList *objects, *l;
 
349
  GList *interfaces, *ll;
 
350
 
 
351
  ret = FALSE;
 
352
 
 
353
  /* This method needs to be idempotent to work with the singleton
 
354
   * pattern. See the docs for g_initable_init(). We implement this by
 
355
   * locking.
 
356
   */
 
357
  G_LOCK (init_lock);
 
358
  if (client->is_initialized)
 
359
    {
 
360
      if (client->object_manager != NULL)
 
361
        ret = TRUE;
 
362
      else
 
363
        g_assert (client->initialization_error != NULL);
 
364
      goto out;
 
365
    }
 
366
  g_assert (client->initialization_error == NULL);
 
367
 
 
368
  client->context = g_main_context_get_thread_default ();
 
369
  if (client->context != NULL)
 
370
    g_main_context_ref (client->context);
 
371
 
 
372
  client->object_manager = udisks_object_manager_client_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
 
373
                                                                          G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
 
374
                                                                          "org.freedesktop.UDisks2",
 
375
                                                                          "/org/freedesktop/UDisks2",
 
376
                                                                          cancellable,
 
377
                                                                          &client->initialization_error);
 
378
  if (client->object_manager == NULL)
 
379
    goto out;
 
380
 
 
381
  /* init all proxies */
 
382
  objects = g_dbus_object_manager_get_objects (client->object_manager);
 
383
  for (l = objects; l != NULL; l = l->next)
 
384
    {
 
385
      interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (l->data));
 
386
      for (ll = interfaces; ll != NULL; ll = ll->next)
 
387
        {
 
388
          init_interface_proxy (client, G_DBUS_PROXY (ll->data));
 
389
        }
 
390
      g_list_foreach (interfaces, (GFunc) g_object_unref, NULL);
 
391
      g_list_free (interfaces);
 
392
    }
 
393
  g_list_foreach (objects, (GFunc) g_object_unref, NULL);
 
394
  g_list_free (objects);
 
395
 
 
396
  g_signal_connect (client->object_manager,
 
397
                    "object-added",
 
398
                    G_CALLBACK (on_object_added),
 
399
                    client);
 
400
  g_signal_connect (client->object_manager,
 
401
                    "object-removed",
 
402
                    G_CALLBACK (on_object_removed),
 
403
                    client);
 
404
  g_signal_connect (client->object_manager,
 
405
                    "interface-added",
 
406
                    G_CALLBACK (on_interface_added),
 
407
                    client);
 
408
  g_signal_connect (client->object_manager,
 
409
                    "interface-removed",
 
410
                    G_CALLBACK (on_interface_removed),
 
411
                    client);
 
412
  g_signal_connect (client->object_manager,
 
413
                    "interface-proxy-properties-changed",
 
414
                    G_CALLBACK (on_interface_proxy_properties_changed),
 
415
                    client);
 
416
 
 
417
  ret = TRUE;
 
418
 
 
419
out:
 
420
  client->is_initialized = TRUE;
 
421
  if (!ret)
 
422
    {
 
423
      g_assert (client->initialization_error != NULL);
 
424
      g_propagate_error (error, g_error_copy (client->initialization_error));
 
425
    }
 
426
  G_UNLOCK (init_lock);
 
427
  return ret;
 
428
}
 
429
 
 
430
static void
 
431
initable_iface_init (GInitableIface      *initable_iface)
 
432
{
 
433
  initable_iface->init = initable_init;
 
434
}
 
435
 
 
436
static void
 
437
async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
 
438
{
 
439
  /* Use default implementation (e.g. run GInitable code in a thread) */
 
440
}
 
441
 
 
442
/**
 
443
 * udisks_client_get_object_manager:
 
444
 * @client: A #UDisksClient.
 
445
 *
 
446
 * Gets the #GDBusObjectManager used by @client.
 
447
 *
 
448
 * Returns: (transfer none): A #GDBusObjectManager. Do not free, the
 
449
 * instance is owned by @client.
 
450
 */
 
451
GDBusObjectManager *
 
452
udisks_client_get_object_manager (UDisksClient        *client)
 
453
{
 
454
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
455
  return client->object_manager;
 
456
}
 
457
 
 
458
/**
 
459
 * udisks_client_get_manager:
 
460
 * @client: A #UDisksClient.
 
461
 *
 
462
 * Gets the #UDisksManager interface on the well-known
 
463
 * <literal>/org/freedesktop/UDisks2/Manager</literal> object.
 
464
 *
 
465
 * Returns: (transfer none): A #UDisksManager or %NULL if the udisksd
 
466
 * daemon is not currently running. Do not free, the instance is owned
 
467
 * by @client.
 
468
 */
 
469
UDisksManager *
 
470
udisks_client_get_manager (UDisksClient *client)
 
471
{
 
472
  UDisksManager *ret = NULL;
 
473
  GDBusObject *obj;
 
474
 
 
475
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
476
 
 
477
  obj = g_dbus_object_manager_get_object (client->object_manager, "/org/freedesktop/UDisks2/Manager");
 
478
  if (obj == NULL)
 
479
    goto out;
 
480
 
 
481
  ret = udisks_object_peek_manager (UDISKS_OBJECT (obj));
 
482
  g_object_unref (obj);
 
483
 
 
484
 out:
 
485
  return ret;
 
486
}
 
487
 
 
488
/**
 
489
 * udisks_client_settle:
 
490
 * @client: A #UDisksClient.
 
491
 *
 
492
 * Blocks until all pending D-Bus messages have been delivered. Also
 
493
 * emits the (rate-limited) #UDisksClient::changed signal if changes
 
494
 * are currently pending.
 
495
 *
 
496
 * This is useful in two situations: 1. when using synchronous method
 
497
 * calls since e.g. D-Bus signals received while waiting for the reply
 
498
 * are queued up and dispatched after the synchronous call ends; and
 
499
 * 2. when using asynchronous calls where the return value references
 
500
 * a newly created object (such as the <link
 
501
 * linkend="gdbus-method-org-freedesktop-UDisks2-Manager.LoopSetup">Manager.LoopSetup()</link> method).
 
502
 */
 
503
void
 
504
udisks_client_settle (UDisksClient *client)
 
505
{
 
506
  while (g_main_context_iteration (client->context, FALSE /* may_block */))
 
507
    ;
 
508
  /* TODO: careful if on different thread... */
 
509
  maybe_emit_changed_now (client);
 
510
}
 
511
 
 
512
/* ---------------------------------------------------------------------------------------------------- */
 
513
 
 
514
/**
 
515
 * udisks_client_get_object:
 
516
 * @client: A #UDisksClient.
 
517
 * @object_path: Object path.
 
518
 *
 
519
 * Convenience function for looking up an #UDisksObject for @object_path.
 
520
 *
 
521
 * Returns: (transfer full): A #UDisksObject corresponding to
 
522
 * @object_path or %NULL if not found. The returned object must be
 
523
 * freed with g_object_unref().
 
524
 */
 
525
UDisksObject *
 
526
udisks_client_get_object (UDisksClient  *client,
 
527
                          const gchar   *object_path)
 
528
{
 
529
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
530
  return (UDisksObject *) g_dbus_object_manager_get_object (client->object_manager, object_path);
 
531
}
 
532
 
 
533
/**
 
534
 * udisks_client_peek_object:
 
535
 * @client: A #UDisksClient.
 
536
 * @object_path: Object path.
 
537
 *
 
538
 * Like udisks_client_get_object() but doesn't increase the reference
 
539
 * count on the returned #UDisksObject.
 
540
 *
 
541
 * <warning>The returned object is only valid until removed so it is only safe to use this function on the thread where @client was constructed. Use udisks_client_get_object() if on another thread.</warning>
 
542
 *
 
543
 * Returns: (transfer none): A #UDisksObject corresponding to
 
544
 * @object_path or %NULL if not found.
 
545
 */
 
546
UDisksObject *
 
547
udisks_client_peek_object (UDisksClient  *client,
 
548
                           const gchar   *object_path)
 
549
{
 
550
  UDisksObject *ret;
 
551
  ret = udisks_client_get_object (client, object_path);
 
552
  if (ret != NULL)
 
553
    g_object_unref (ret);
 
554
  return ret;
 
555
}
 
556
 
 
557
/* ---------------------------------------------------------------------------------------------------- */
 
558
 
 
559
/**
 
560
 * udisks_client_get_block_for_label:
 
561
 * @client: A #UDisksClient.
 
562
 * @label: The label.
 
563
 *
 
564
 * Gets all the #UDisksBlock instances with the given label, if any.
 
565
 *
 
566
 * Returns: (transfer full) (element-type UDisksBlock): A list of #UDisksBlock instances. The
 
567
 *   returned list should be freed with g_list_free() after each
 
568
 *   element has been freed with g_object_unref().
 
569
 */
 
570
GList *
 
571
udisks_client_get_block_for_label (UDisksClient        *client,
 
572
                                   const gchar         *label)
 
573
{
 
574
  GList *ret = NULL;
 
575
  GList *l, *object_proxies = NULL;
 
576
 
 
577
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
578
  g_return_val_if_fail (label != NULL, NULL);
 
579
 
 
580
  object_proxies = g_dbus_object_manager_get_objects (client->object_manager);
 
581
  for (l = object_proxies; l != NULL; l = l->next)
 
582
    {
 
583
      UDisksObject *object = UDISKS_OBJECT (l->data);
 
584
      UDisksBlock *block;
 
585
 
 
586
      block = udisks_object_get_block (object);
 
587
      if (block == NULL)
 
588
        continue;
 
589
 
 
590
      if (g_strcmp0 (udisks_block_get_id_label (block), label) == 0)
 
591
        ret = g_list_prepend (ret, block);
 
592
      else
 
593
        g_object_unref (block);
 
594
    }
 
595
 
 
596
  g_list_foreach (object_proxies, (GFunc) g_object_unref, NULL);
 
597
  g_list_free (object_proxies);
 
598
  ret = g_list_reverse (ret);
 
599
  return ret;
 
600
}
 
601
 
 
602
/* ---------------------------------------------------------------------------------------------------- */
 
603
 
 
604
/**
 
605
 * udisks_client_get_block_for_uuid:
 
606
 * @client: A #UDisksClient.
 
607
 * @uuid: The uuid.
 
608
 *
 
609
 * Gets all the #UDisksBlock instances with the given uuid, if any.
 
610
 *
 
611
 * Returns: (transfer full) (element-type UDisksBlock): A list of #UDisksBlock instances. The
 
612
 *   returned list should be freed with g_list_free() after each
 
613
 *   element has been freed with g_object_unref().
 
614
 */
 
615
GList *
 
616
udisks_client_get_block_for_uuid (UDisksClient        *client,
 
617
                                  const gchar         *uuid)
 
618
{
 
619
  GList *ret = NULL;
 
620
  GList *l, *object_proxies = NULL;
 
621
 
 
622
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
623
  g_return_val_if_fail (uuid != NULL, NULL);
 
624
 
 
625
  object_proxies = g_dbus_object_manager_get_objects (client->object_manager);
 
626
  for (l = object_proxies; l != NULL; l = l->next)
 
627
    {
 
628
      UDisksObject *object = UDISKS_OBJECT (l->data);
 
629
      UDisksBlock *block;
 
630
 
 
631
      block = udisks_object_get_block (object);
 
632
      if (block == NULL)
 
633
        continue;
 
634
 
 
635
      if (g_strcmp0 (udisks_block_get_id_uuid (block), uuid) == 0)
 
636
        ret = g_list_prepend (ret, block);
 
637
      else
 
638
        g_object_unref (block);
 
639
    }
 
640
 
 
641
  g_list_foreach (object_proxies, (GFunc) g_object_unref, NULL);
 
642
  g_list_free (object_proxies);
 
643
  ret = g_list_reverse (ret);
 
644
  return ret;
 
645
}
 
646
 
 
647
/* ---------------------------------------------------------------------------------------------------- */
 
648
 
 
649
/* Note: The (type guint64) is a workaround for g-i mishandling dev_t, see
 
650
 * https://bugzilla.gnome.org/show_bug.cgi?id=584517 */
 
651
 
 
652
/**
 
653
 * udisks_client_get_block_for_dev:
 
654
 * @client: A #UDisksClient.
 
655
 * @block_device_number: (type guint64): A #dev_t to get a #UDisksBlock for.
 
656
 *
 
657
 * Gets the #UDisksBlock corresponding to @block_device_number, if any.
 
658
 *
 
659
 * Returns: (transfer full): A #UDisksBlock or %NULL if not found.
 
660
 */
 
661
UDisksBlock *
 
662
udisks_client_get_block_for_dev (UDisksClient *client,
 
663
                                 dev_t         block_device_number)
 
664
{
 
665
  UDisksBlock *ret = NULL;
 
666
  GList *l, *object_proxies = NULL;
 
667
 
 
668
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
669
 
 
670
  object_proxies = g_dbus_object_manager_get_objects (client->object_manager);
 
671
  for (l = object_proxies; l != NULL; l = l->next)
 
672
    {
 
673
      UDisksObject *object = UDISKS_OBJECT (l->data);
 
674
      UDisksBlock *block;
 
675
 
 
676
      block = udisks_object_get_block (object);
 
677
      if (block == NULL)
 
678
        continue;
 
679
 
 
680
      if (udisks_block_get_device_number (block) == block_device_number)
 
681
        {
 
682
          ret = block;
 
683
          goto out;
 
684
        }
 
685
      g_object_unref (block);
 
686
    }
 
687
 
 
688
 out:
 
689
  g_list_foreach (object_proxies, (GFunc) g_object_unref, NULL);
 
690
  g_list_free (object_proxies);
 
691
  return ret;
 
692
}
 
693
 
 
694
/* ---------------------------------------------------------------------------------------------------- */
 
695
 
 
696
static GList *
 
697
get_top_level_blocks_for_drive (UDisksClient *client,
 
698
                                const gchar  *drive_object_path)
 
699
{
 
700
  GList *ret;
 
701
  GList *l;
 
702
  GList *object_proxies;
 
703
  GDBusObjectManager *object_manager;
 
704
 
 
705
  object_manager = udisks_client_get_object_manager (client);
 
706
  object_proxies = g_dbus_object_manager_get_objects (object_manager);
 
707
 
 
708
  ret = NULL;
 
709
  for (l = object_proxies; l != NULL; l = l->next)
 
710
    {
 
711
      UDisksObject *object = UDISKS_OBJECT (l->data);
 
712
      UDisksBlock *block;
 
713
      UDisksPartition *partition;
 
714
 
 
715
      block = udisks_object_get_block (object);
 
716
      partition = udisks_object_peek_partition (object);
 
717
      if (block == NULL)
 
718
        continue;
 
719
 
 
720
      if (g_strcmp0 (udisks_block_get_drive (block), drive_object_path) == 0 &&
 
721
          partition == NULL)
 
722
        {
 
723
          ret = g_list_append (ret, g_object_ref (object));
 
724
        }
 
725
      g_object_unref (block);
 
726
    }
 
727
  g_list_foreach (object_proxies, (GFunc) g_object_unref, NULL);
 
728
  g_list_free (object_proxies);
 
729
  return ret;
 
730
}
 
731
 
 
732
/**
 
733
 * udisks_client_get_block_for_drive:
 
734
 * @client: A #UDisksClient.
 
735
 * @drive: A #UDisksDrive.
 
736
 * @get_physical: %TRUE to get a physical device, %FALSE to get the logical device.
 
737
 *
 
738
 * Gets a block device corresponding to @drive. The returned block
 
739
 * device, if any, is for the whole disk drive, e.g. a partition block
 
740
 * device is never returned.
 
741
 *
 
742
 * Set @get_physical to %TRUE if you need a block device that you can
 
743
 * send low-level SCSI commands with (for multipath, this returns one
 
744
 * of the physical paths). Set it to %FALSE if you need a block device
 
745
 * that you can read/write data with (for multipath, this returns the
 
746
 * mapped device).
 
747
 *
 
748
 * Returns: (transfer full): A #UDisksBlock or %NULL if the requested
 
749
 * kind of block device is not available - use g_object_unref() to
 
750
 * free the returned object.
 
751
 */
 
752
UDisksBlock *
 
753
udisks_client_get_block_for_drive (UDisksClient        *client,
 
754
                                   UDisksDrive         *drive,
 
755
                                   gboolean             get_physical)
 
756
{
 
757
  UDisksBlock *ret = NULL;
 
758
  GDBusObject *object;
 
759
  GList *blocks = NULL;
 
760
  GList *l;
 
761
 
 
762
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
763
  g_return_val_if_fail (UDISKS_IS_DRIVE (drive), NULL);
 
764
 
 
765
  object = g_dbus_interface_get_object (G_DBUS_INTERFACE (drive));
 
766
  if (object == NULL)
 
767
    goto out;
 
768
 
 
769
  blocks = get_top_level_blocks_for_drive (client, g_dbus_object_get_object_path (object));
 
770
  for (l = blocks; l != NULL; l = l->next)
 
771
    {
 
772
      UDisksBlock *block = udisks_object_peek_block (UDISKS_OBJECT (l->data));
 
773
      if (block != NULL)
 
774
        {
 
775
          /* TODO: actually look at @get_physical */
 
776
          ret = g_object_ref (block);
 
777
          goto out;
 
778
        }
 
779
    }
 
780
 
 
781
 out:
 
782
  g_list_foreach (blocks, (GFunc) g_object_unref, NULL);
 
783
  g_list_free (blocks);
 
784
  return ret;
 
785
}
 
786
 
 
787
/**
 
788
 * udisks_client_get_drive_for_block:
 
789
 * @client: A #UDisksClient.
 
790
 * @block: A #UDisksBlock.
 
791
 *
 
792
 * Gets the #UDisksDrive that @block belongs to, if any.
 
793
 *
 
794
 * Returns: (transfer full): A #UDisksDrive or %NULL if there is no
 
795
 * #UDisksDrive for @block - free the returned object with
 
796
 * g_object_unref().
 
797
 */
 
798
UDisksDrive *
 
799
udisks_client_get_drive_for_block (UDisksClient  *client,
 
800
                                   UDisksBlock   *block)
 
801
{
 
802
  UDisksDrive *ret = NULL;
 
803
  GDBusObject *object;
 
804
 
 
805
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
806
  g_return_val_if_fail (UDISKS_IS_BLOCK (block), NULL);
 
807
 
 
808
  object = g_dbus_object_manager_get_object (client->object_manager, udisks_block_get_drive (block));
 
809
  if (object != NULL)
 
810
    ret = udisks_object_get_drive (UDISKS_OBJECT (object));
 
811
  return ret;
 
812
}
 
813
 
 
814
/* ---------------------------------------------------------------------------------------------------- */
 
815
 
 
816
/**
 
817
 * udisks_client_get_mdraid_for_block:
 
818
 * @client: A #UDisksClient.
 
819
 * @block: A #UDisksBlock.
 
820
 *
 
821
 * Gets the #UDisksMDRaid that @block is the block device for, if any.
 
822
 *
 
823
 * Returns: (transfer full): A #UDisksMDRaid or %NULL if there is no
 
824
 *   #UDisksMDRaid for @block or @block is not a MD-RAID block
 
825
 *   device. Free the returned object with g_object_unref().
 
826
 *
 
827
 * Since: 2.1
 
828
 */
 
829
UDisksMDRaid *
 
830
udisks_client_get_mdraid_for_block (UDisksClient  *client,
 
831
                                    UDisksBlock   *block)
 
832
{
 
833
  UDisksMDRaid *ret = NULL;
 
834
  GDBusObject *object;
 
835
 
 
836
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
837
  g_return_val_if_fail (UDISKS_IS_BLOCK (block), NULL);
 
838
 
 
839
  object = g_dbus_object_manager_get_object (client->object_manager, udisks_block_get_mdraid (block));
 
840
  if (object != NULL)
 
841
    ret = udisks_object_get_mdraid (UDISKS_OBJECT (object));
 
842
  return ret;
 
843
}
 
844
 
 
845
/* ---------------------------------------------------------------------------------------------------- */
 
846
 
 
847
/**
 
848
 * udisks_client_get_block_for_mdraid:
 
849
 * @client: A #UDisksClient.
 
850
 * @raid: A #UDisksMDRaid.
 
851
 *
 
852
 * Gets the RAID device (e.g. <filename>/dev/md0</filename>) for @raid.
 
853
 *
 
854
 * In the case of a <ulink
 
855
 * url="http://en.wikipedia.org/wiki/Split-brain_(computing)">split-brain
 
856
 * syndrome</ulink>, it is undefined which RAID device is
 
857
 * returned. For example this can happen if
 
858
 * <filename>/dev/sda</filename> and <filename>/dev/sdb</filename> are
 
859
 * components of a two-disk RAID-1 and <filename>/dev/md0</filename>
 
860
 * and <filename>/dev/md1</filename> are two degraded arrays, each one
 
861
 * using exactly one of the two devices. Use
 
862
 * udisks_client_get_all_blocks_for_mdraid() to get all RAID devices.
 
863
 *
 
864
 * Returns: (transfer full): A #UDisksBlock or %NULL if no RAID device is running.
 
865
 *
 
866
 * Since: 2.1
 
867
 */
 
868
UDisksBlock *
 
869
udisks_client_get_block_for_mdraid (UDisksClient *client,
 
870
                                    UDisksMDRaid *raid)
 
871
{
 
872
  UDisksBlock *ret = NULL;
 
873
  GList *l, *object_proxies = NULL;
 
874
  GDBusObject *raid_object;
 
875
  const gchar *raid_objpath;
 
876
 
 
877
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
878
  g_return_val_if_fail (UDISKS_IS_MDRAID (raid), NULL);
 
879
 
 
880
  raid_object = g_dbus_interface_get_object (G_DBUS_INTERFACE (raid));
 
881
  if (raid_object == NULL)
 
882
    goto out;
 
883
 
 
884
  raid_objpath = g_dbus_object_get_object_path (raid_object);
 
885
 
 
886
  object_proxies = g_dbus_object_manager_get_objects (client->object_manager);
 
887
  for (l = object_proxies; l != NULL; l = l->next)
 
888
    {
 
889
      UDisksObject *object = UDISKS_OBJECT (l->data);
 
890
      UDisksBlock *block;
 
891
 
 
892
      block = udisks_object_get_block (object);
 
893
      if (block == NULL)
 
894
        continue;
 
895
 
 
896
      /* ignore partitions */
 
897
      if (udisks_object_peek_partition (object) != NULL)
 
898
        continue;
 
899
 
 
900
      if (g_strcmp0 (udisks_block_get_mdraid (block), raid_objpath) == 0)
 
901
        {
 
902
          ret = block;
 
903
          goto out;
 
904
        }
 
905
      g_object_unref (block);
 
906
    }
 
907
 
 
908
 out:
 
909
  g_list_foreach (object_proxies, (GFunc) g_object_unref, NULL);
 
910
  g_list_free (object_proxies);
 
911
  return ret;
 
912
}
 
913
 
 
914
/**
 
915
 * udisks_client_get_all_blocks_for_mdraid:
 
916
 * @client: A #UDisksClient.
 
917
 * @raid: A #UDisksMDRaid.
 
918
 *
 
919
 * Gets all RAID devices (e.g. <filename>/dev/md0</filename> and <filename>/dev/md1</filename>) for @raid.
 
920
 *
 
921
 * This is usually only useful in <ulink
 
922
 * url="http://en.wikipedia.org/wiki/Split-brain_(computing)">split-brain
 
923
 * situations</ulink> — see udisks_client_get_block_for_mdraid() for
 
924
 * an example — and is normally used only to convey the problem in an
 
925
 * user interface.
 
926
 *
 
927
 * Returns: (transfer full) (element-type UDisksBlock): A list of #UDisksBlock instances. The
 
928
 *   returned list should be freed with g_list_free() after each
 
929
 *   element has been freed with g_object_unref().
 
930
 *
 
931
 * Since: 2.1
 
932
 */
 
933
GList *
 
934
udisks_client_get_all_blocks_for_mdraid (UDisksClient *client,
 
935
                                         UDisksMDRaid *raid)
 
936
{
 
937
  GList *ret = NULL;
 
938
  GList *l, *object_proxies = NULL;
 
939
  GDBusObject *raid_object;
 
940
  const gchar *raid_objpath;
 
941
 
 
942
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
943
  g_return_val_if_fail (UDISKS_IS_MDRAID (raid), NULL);
 
944
 
 
945
  raid_object = g_dbus_interface_get_object (G_DBUS_INTERFACE (raid));
 
946
  if (raid_object == NULL)
 
947
    goto out;
 
948
 
 
949
  raid_objpath = g_dbus_object_get_object_path (raid_object);
 
950
 
 
951
  object_proxies = g_dbus_object_manager_get_objects (client->object_manager);
 
952
  for (l = object_proxies; l != NULL; l = l->next)
 
953
    {
 
954
      UDisksObject *object = UDISKS_OBJECT (l->data);
 
955
      UDisksBlock *block;
 
956
 
 
957
      block = udisks_object_get_block (object);
 
958
      if (block == NULL)
 
959
        continue;
 
960
 
 
961
      /* ignore partitions */
 
962
      if (udisks_object_peek_partition (object) != NULL)
 
963
        continue;
 
964
 
 
965
      if (g_strcmp0 (udisks_block_get_mdraid (block), raid_objpath) == 0)
 
966
        {
 
967
          ret = g_list_prepend (ret, block);
 
968
        }
 
969
      else
 
970
        {
 
971
          g_object_unref (block);
 
972
        }
 
973
    }
 
974
 
 
975
 out:
 
976
  g_list_foreach (object_proxies, (GFunc) g_object_unref, NULL);
 
977
  g_list_free (object_proxies);
 
978
  ret = g_list_reverse (ret);
 
979
  return ret;
 
980
}
 
981
 
 
982
/**
 
983
 * udisks_client_get_members_for_mdraid:
 
984
 * @client: A #UDisksClient.
 
985
 * @raid: A #UDisksMDRaid.
 
986
 *
 
987
 * Gets the physical block devices that are part of @raid.
 
988
 *
 
989
 * Returns: (transfer full) (element-type UDisksBlock): A list of #UDisksBlock instances. The
 
990
 *   returned list should be freed with g_list_free() after each
 
991
 *   element has been freed with g_object_unref().
 
992
 *
 
993
 * Since: 2.1
 
994
 */
 
995
GList *
 
996
udisks_client_get_members_for_mdraid (UDisksClient *client,
 
997
                                      UDisksMDRaid *raid)
 
998
{
 
999
  GList *ret = NULL;
 
1000
  GList *l, *object_proxies = NULL;
 
1001
  GDBusObject *raid_object;
 
1002
  const gchar *raid_objpath;
 
1003
 
 
1004
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
1005
  g_return_val_if_fail (UDISKS_IS_MDRAID (raid), NULL);
 
1006
 
 
1007
  raid_object = g_dbus_interface_get_object (G_DBUS_INTERFACE (raid));
 
1008
  if (raid_object == NULL)
 
1009
    goto out;
 
1010
 
 
1011
  raid_objpath = g_dbus_object_get_object_path (raid_object);
 
1012
 
 
1013
  object_proxies = g_dbus_object_manager_get_objects (client->object_manager);
 
1014
  for (l = object_proxies; l != NULL; l = l->next)
 
1015
    {
 
1016
      UDisksObject *object = UDISKS_OBJECT (l->data);
 
1017
      UDisksBlock *block;
 
1018
 
 
1019
      block = udisks_object_get_block (object);
 
1020
      if (block == NULL)
 
1021
        continue;
 
1022
 
 
1023
      if (g_strcmp0 (udisks_block_get_mdraid_member (block), raid_objpath) == 0)
 
1024
        {
 
1025
          ret = g_list_prepend (ret, block); /* adopts reference to block */
 
1026
        }
 
1027
      else
 
1028
        {
 
1029
          g_object_unref (block);
 
1030
        }
 
1031
    }
 
1032
 
 
1033
 out:
 
1034
  g_list_foreach (object_proxies, (GFunc) g_object_unref, NULL);
 
1035
  g_list_free (object_proxies);
 
1036
  return ret;
 
1037
}
 
1038
 
 
1039
/* ---------------------------------------------------------------------------------------------------- */
 
1040
 
 
1041
static void
 
1042
add_item (gchar **items_str,
 
1043
          const gchar *item)
 
1044
{
 
1045
  gchar *orig = *items_str;
 
1046
  if (*items_str == NULL)
 
1047
    {
 
1048
      *items_str = g_strdup (item);
 
1049
      g_free (orig);
 
1050
    }
 
1051
  else
 
1052
    {
 
1053
      *items_str = g_strdup_printf ("%s, %s", orig, item);
 
1054
      g_free (orig);
 
1055
    }
 
1056
}
 
1057
 
 
1058
/**
 
1059
 * udisks_client_get_partition_info:
 
1060
 * @client: A #UDisksClient.
 
1061
 * @partition: # #UDisksPartition.
 
1062
 *
 
1063
 * Gets information about @partition that is suitable to present in an
 
1064
 * user interface in a single line of text.
 
1065
 *
 
1066
 * The returned string is localized and includes things like the
 
1067
 * partition type, flags (if any) and name (if any).
 
1068
 *
 
1069
 * Returns: (transfer full): A string that should be freed with g_free().
 
1070
 */
 
1071
gchar *
 
1072
udisks_client_get_partition_info (UDisksClient    *client,
 
1073
                                  UDisksPartition *partition)
 
1074
{
 
1075
  gchar *ret = NULL;
 
1076
  const gchar *type_str = NULL;
 
1077
  gchar *flags_str = NULL;
 
1078
  UDisksPartitionTable *table = NULL;
 
1079
  guint64 flags;
 
1080
 
 
1081
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
1082
  g_return_val_if_fail (UDISKS_IS_PARTITION (partition), NULL);
 
1083
 
 
1084
  table = udisks_client_get_partition_table (client, partition);
 
1085
  if (table == NULL)
 
1086
    goto out;
 
1087
 
 
1088
  flags = udisks_partition_get_flags (partition);
 
1089
  if (g_strcmp0 (udisks_partition_table_get_type_ (table), "dos") == 0)
 
1090
    {
 
1091
      if (flags & 0x80)
 
1092
        {
 
1093
          /* Translators: Corresponds to the DOS/Master-Boot-Record "bootable" flag for a partition */
 
1094
          add_item (&flags_str, C_("dos-part-flag", "Bootable"));
 
1095
        }
 
1096
    }
 
1097
  else if (g_strcmp0 (udisks_partition_table_get_type_ (table), "gpt") == 0)
 
1098
    {
 
1099
      if (flags & (1ULL<<0))
 
1100
        {
 
1101
          /* Translators: Corresponds to the GPT "system" flag for a partition,
 
1102
           * see http://en.wikipedia.org/wiki/GUID_Partition_Table
 
1103
           */
 
1104
          add_item (&flags_str, C_("gpt-part-flag", "System"));
 
1105
        }
 
1106
      if (flags & (1ULL<<2))
 
1107
        {
 
1108
          /* Translators: Corresponds to the GPT "legacy bios bootable" flag for a partition,
 
1109
           * see http://en.wikipedia.org/wiki/GUID_Partition_Table
 
1110
           */
 
1111
          add_item (&flags_str, C_("gpt-part-flag", "Legacy BIOS Bootable"));
 
1112
        }
 
1113
      if (flags & (1ULL<<60))
 
1114
        {
 
1115
          /* Translators: Corresponds to the GPT "read-only" flag for a partition,
 
1116
           * see http://en.wikipedia.org/wiki/GUID_Partition_Table
 
1117
           */
 
1118
          add_item (&flags_str, C_("gpt-part-flag", "Read-only"));
 
1119
        }
 
1120
      if (flags & (1ULL<<62))
 
1121
        {
 
1122
          /* Translators: Corresponds to the GPT "hidden" flag for a partition,
 
1123
           * see http://en.wikipedia.org/wiki/GUID_Partition_Table
 
1124
           */
 
1125
          add_item (&flags_str, C_("gpt-part-flag", "Hidden"));
 
1126
        }
 
1127
      if (flags & (1ULL<<63))
 
1128
        {
 
1129
          /* Translators: Corresponds to the GPT "no automount" flag for a partition,
 
1130
           * see http://en.wikipedia.org/wiki/GUID_Partition_Table
 
1131
           */
 
1132
          add_item (&flags_str, C_("gpt-part-flag", "No Automount"));
 
1133
        }
 
1134
    }
 
1135
 
 
1136
  type_str = udisks_client_get_partition_type_for_display (client,
 
1137
                                                           udisks_partition_table_get_type_ (table),
 
1138
                                                           udisks_partition_get_type_ (partition));
 
1139
  if (type_str == NULL)
 
1140
    type_str = udisks_partition_get_type_ (partition);
 
1141
 
 
1142
  if (flags_str != NULL)
 
1143
    {
 
1144
      /* Translators: Partition info. First %s is the type, second %s is a list of flags */
 
1145
      ret = g_strdup_printf (C_("partition-info", "%s (%s)"), type_str, flags_str);
 
1146
    }
 
1147
  else
 
1148
    {
 
1149
      ret = g_strdup (type_str);
 
1150
    }
 
1151
 
 
1152
  if (ret == NULL || strlen (ret) == 0)
 
1153
    {
 
1154
      g_free (ret);
 
1155
      /* Translators: The Partition info when unknown */
 
1156
      ret = g_strdup (C_("partition-info", "Unknown"));
 
1157
    }
 
1158
 
 
1159
  g_free (flags_str);
 
1160
  g_object_unref (table);
 
1161
 out:
 
1162
  return ret;
 
1163
}
 
1164
 
 
1165
/* ---------------------------------------------------------------------------------------------------- */
 
1166
 
 
1167
/**
 
1168
 * udisks_client_get_cleartext_block:
 
1169
 * @client: A #UDisksClient.
 
1170
 * @block: A #UDisksBlock.
 
1171
 *
 
1172
 * If @block is an unlocked encrypted device, gets the cleartext device.
 
1173
 *
 
1174
 * Returns: (transfer full): A #UDisksBlock or %NULL. Free with
 
1175
 * g_object_unref() when done with it.
 
1176
 */
 
1177
UDisksBlock *
 
1178
udisks_client_get_cleartext_block (UDisksClient  *client,
 
1179
                                   UDisksBlock   *block)
 
1180
{
 
1181
  UDisksBlock *ret = NULL;
 
1182
  GDBusObject *object;
 
1183
  const gchar *object_path;
 
1184
  GList *objects = NULL;
 
1185
  GList *l;
 
1186
 
 
1187
  object = g_dbus_interface_get_object (G_DBUS_INTERFACE (block));
 
1188
  if (object == NULL)
 
1189
    goto out;
 
1190
 
 
1191
  object_path = g_dbus_object_get_object_path (object);
 
1192
  objects = g_dbus_object_manager_get_objects (client->object_manager);
 
1193
  for (l = objects; l != NULL; l = l->next)
 
1194
    {
 
1195
      UDisksObject *iter_object = UDISKS_OBJECT (l->data);
 
1196
      UDisksBlock *iter_block;
 
1197
 
 
1198
      iter_block = udisks_object_peek_block (iter_object);
 
1199
      if (iter_block == NULL)
 
1200
        continue;
 
1201
 
 
1202
      if (g_strcmp0 (udisks_block_get_crypto_backing_device (iter_block), object_path) == 0)
 
1203
        {
 
1204
          ret = g_object_ref (iter_block);
 
1205
          goto out;
 
1206
        }
 
1207
    }
 
1208
 
 
1209
 out:
 
1210
  g_list_foreach (objects, (GFunc) g_object_unref, NULL);
 
1211
  g_list_free (objects);
 
1212
  return ret;
 
1213
}
 
1214
 
 
1215
/* ---------------------------------------------------------------------------------------------------- */
 
1216
 
 
1217
/**
 
1218
 * udisks_client_get_drive_siblings:
 
1219
 * @client: A #UDisksClient
 
1220
 * @drive: A #UDisksDrive.
 
1221
 *
 
1222
 * Gets all siblings for @drive.
 
1223
 *
 
1224
 * Returns: (transfer full) (element-type UDisksDrive): A list of #UDisksDrive instances. The
 
1225
 *   returned list should be freed with g_list_free() after each element has been
 
1226
 *   freed with g_object_unref().
 
1227
 *
 
1228
 * Since: 2.1
 
1229
 */
 
1230
GList *
 
1231
udisks_client_get_drive_siblings  (UDisksClient  *client,
 
1232
                                   UDisksDrive   *drive)
 
1233
{
 
1234
  GList *ret = NULL;
 
1235
  const gchar *sibling_id = NULL;
 
1236
  GList *l, *object_proxies = NULL;
 
1237
 
 
1238
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
1239
  g_return_val_if_fail (UDISKS_IS_DRIVE (drive), NULL);
 
1240
 
 
1241
  sibling_id = udisks_drive_get_sibling_id (drive);
 
1242
  if (sibling_id == NULL || strlen (sibling_id) == 0)
 
1243
    goto out;
 
1244
 
 
1245
  object_proxies = g_dbus_object_manager_get_objects (client->object_manager);
 
1246
  for (l = object_proxies; l != NULL; l = l->next)
 
1247
    {
 
1248
      UDisksObject *object = UDISKS_OBJECT (l->data);
 
1249
      UDisksDrive *iter_drive;
 
1250
 
 
1251
      iter_drive = udisks_object_get_drive (object);
 
1252
      if (iter_drive == NULL)
 
1253
        continue;
 
1254
 
 
1255
      if (iter_drive != drive &&
 
1256
          g_strcmp0 (udisks_drive_get_sibling_id (iter_drive), sibling_id) == 0)
 
1257
        {
 
1258
          ret = g_list_prepend (ret, g_object_ref (iter_drive));
 
1259
        }
 
1260
 
 
1261
      g_object_unref (iter_drive);
 
1262
    }
 
1263
  ret = g_list_reverse (ret);
 
1264
 out:
 
1265
  g_list_foreach (object_proxies, (GFunc) g_object_unref, NULL);
 
1266
  g_list_free (object_proxies);
 
1267
  return ret;
 
1268
}
 
1269
 
 
1270
/* ---------------------------------------------------------------------------------------------------- */
 
1271
 
 
1272
/**
 
1273
 * udisks_client_get_partitions:
 
1274
 * @client: A #UDisksClient.
 
1275
 * @table: A #UDisksPartitionTable.
 
1276
 *
 
1277
 * Gets all partitions of @table.
 
1278
 *
 
1279
 * Returns: (transfer full) (element-type UDisksPartition): A list of #UDisksPartition instances. The
 
1280
 *   returned list should be freed with g_list_free() after each
 
1281
 *   element has been freed with g_object_unref().
 
1282
 */
 
1283
GList *
 
1284
udisks_client_get_partitions (UDisksClient         *client,
 
1285
                              UDisksPartitionTable *table)
 
1286
{
 
1287
  GList *ret = NULL;
 
1288
  GDBusObject *table_object;
 
1289
  const gchar *table_object_path;
 
1290
  GList *l, *object_proxies = NULL;
 
1291
 
 
1292
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
1293
  g_return_val_if_fail (UDISKS_IS_PARTITION_TABLE (table), NULL);
 
1294
 
 
1295
  table_object = g_dbus_interface_get_object (G_DBUS_INTERFACE (table));
 
1296
  if (table_object == NULL)
 
1297
    goto out;
 
1298
  table_object_path = g_dbus_object_get_object_path (table_object);
 
1299
 
 
1300
  object_proxies = g_dbus_object_manager_get_objects (client->object_manager);
 
1301
  for (l = object_proxies; l != NULL; l = l->next)
 
1302
    {
 
1303
      UDisksObject *object = UDISKS_OBJECT (l->data);
 
1304
      UDisksPartition *partition;
 
1305
 
 
1306
      partition = udisks_object_get_partition (object);
 
1307
      if (partition == NULL)
 
1308
        continue;
 
1309
 
 
1310
      if (g_strcmp0 (udisks_partition_get_table (partition), table_object_path) == 0)
 
1311
        ret = g_list_prepend (ret, g_object_ref (partition));
 
1312
 
 
1313
      g_object_unref (partition);
 
1314
    }
 
1315
  ret = g_list_reverse (ret);
 
1316
 out:
 
1317
  g_list_foreach (object_proxies, (GFunc) g_object_unref, NULL);
 
1318
  g_list_free (object_proxies);
 
1319
  return ret;
 
1320
}
 
1321
 
 
1322
/**
 
1323
 * udisks_client_get_partition_table:
 
1324
 * @client: A #UDisksClient.
 
1325
 * @partition: A #UDisksPartition.
 
1326
 *
 
1327
 * Gets the #UDisksPartitionTable corresponding to @partition.
 
1328
 *
 
1329
 * Returns: (transfer full): A #UDisksPartitionTable. Free with g_object_unref().
 
1330
 */
 
1331
UDisksPartitionTable *
 
1332
udisks_client_get_partition_table (UDisksClient     *client,
 
1333
                                   UDisksPartition  *partition)
 
1334
{
 
1335
  UDisksPartitionTable *ret = NULL;
 
1336
  UDisksObject *object;
 
1337
 
 
1338
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
1339
  g_return_val_if_fail (UDISKS_IS_PARTITION (partition), NULL);
 
1340
 
 
1341
  object = udisks_client_get_object (client, udisks_partition_get_table (partition));
 
1342
  if (object == NULL)
 
1343
    goto out;
 
1344
 
 
1345
  ret = udisks_object_get_partition_table (object);
 
1346
  g_object_unref (object);
 
1347
 
 
1348
 out:
 
1349
  return ret;
 
1350
}
 
1351
 
 
1352
/**
 
1353
 * udisks_client_get_loop_for_block:
 
1354
 * @client: A #UDisksClient.
 
1355
 * @block: A #UDisksBlock.
 
1356
 *
 
1357
 * Gets the corresponding loop interface for @block.
 
1358
 *
 
1359
 * This only works if @block itself is a loop device or a partition of
 
1360
 * a loop device.
 
1361
 *
 
1362
 * Returns: (transfer full): A #UDisksLoop or %NULL. Free with g_object_unref().
 
1363
 */
 
1364
UDisksLoop *
 
1365
udisks_client_get_loop_for_block (UDisksClient  *client,
 
1366
                                  UDisksBlock   *block)
 
1367
{
 
1368
  UDisksPartition *partition;
 
1369
  UDisksObject *object = NULL;
 
1370
  UDisksLoop *ret = NULL;
 
1371
 
 
1372
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
1373
  g_return_val_if_fail (UDISKS_IS_BLOCK (block), NULL);
 
1374
 
 
1375
  object = (UDisksObject *) g_dbus_interface_dup_object (G_DBUS_INTERFACE (block));
 
1376
  if (object == NULL)
 
1377
    goto out;
 
1378
 
 
1379
  ret = udisks_object_get_loop (object);
 
1380
  if (ret != NULL)
 
1381
    goto out;
 
1382
 
 
1383
  /* Could be we're a partition of a loop device */
 
1384
  partition = udisks_object_get_partition (object);
 
1385
  if (partition != NULL)
 
1386
    {
 
1387
      UDisksPartitionTable *partition_table;
 
1388
      partition_table = udisks_client_get_partition_table (client, partition);
 
1389
      if (partition_table != NULL)
 
1390
        {
 
1391
          UDisksObject *partition_table_object;
 
1392
          partition_table_object = (UDisksObject *) g_dbus_interface_dup_object (G_DBUS_INTERFACE (partition_table));
 
1393
          if (partition_table_object != NULL)
 
1394
            {
 
1395
              ret = udisks_object_get_loop (UDISKS_OBJECT (partition_table_object));
 
1396
              g_object_unref (partition_table_object);
 
1397
            }
 
1398
          g_object_unref (partition_table);
 
1399
        }
 
1400
      g_object_unref (partition);
 
1401
    }
 
1402
 
 
1403
 out:
 
1404
  g_clear_object (&object);
 
1405
  return ret;
 
1406
}
 
1407
 
 
1408
/* ---------------------------------------------------------------------------------------------------- */
 
1409
 
 
1410
/**
 
1411
 * udisks_client_get_jobs_for_object:
 
1412
 * @client: A #UDisksClient.
 
1413
 * @object: A #UDisksObject.
 
1414
 *
 
1415
 * Gets all the #UDisksJob instances that reference @object, if any.
 
1416
 *
 
1417
 * Returns: (transfer full) (element-type UDisksJob): A list of #UDisksJob instances. The
 
1418
 *   returned list should be freed with g_list_free() after each
 
1419
 *   element has been freed with g_object_unref().
 
1420
 */
 
1421
GList *
 
1422
udisks_client_get_jobs_for_object (UDisksClient  *client,
 
1423
                                   UDisksObject  *object)
 
1424
{
 
1425
  GList *ret = NULL;
 
1426
  const gchar *object_path;
 
1427
  GList *l, *object_proxies = NULL;
 
1428
 
 
1429
  /* TODO: this is probably slow. Can optimize by maintaining a hash-table from object path to UDisksJob* */
 
1430
 
 
1431
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
1432
  g_return_val_if_fail (UDISKS_IS_OBJECT (object), NULL);
 
1433
 
 
1434
  object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
 
1435
 
 
1436
  object_proxies = g_dbus_object_manager_get_objects (client->object_manager);
 
1437
  for (l = object_proxies; l != NULL; l = l->next)
 
1438
    {
 
1439
      UDisksObject *job_object = UDISKS_OBJECT (l->data);
 
1440
      UDisksJob *job;
 
1441
 
 
1442
      job = udisks_object_get_job (job_object);
 
1443
      if (job != NULL)
 
1444
        {
 
1445
          const gchar *const *object_paths;
 
1446
          guint n;
 
1447
          object_paths = udisks_job_get_objects (job);
 
1448
          for (n = 0; object_paths != NULL && object_paths[n] != NULL; n++)
 
1449
            {
 
1450
              if (g_strcmp0 (object_paths[n], object_path) == 0)
 
1451
                ret = g_list_prepend (ret, g_object_ref (job));
 
1452
            }
 
1453
          g_object_unref (job);
 
1454
        }
 
1455
    }
 
1456
  ret = g_list_reverse (ret);
 
1457
 
 
1458
  g_list_foreach (object_proxies, (GFunc) g_object_unref, NULL);
 
1459
  g_list_free (object_proxies);
 
1460
  return ret;
 
1461
}
 
1462
 
 
1463
/* ---------------------------------------------------------------------------------------------------- */
 
1464
 
 
1465
static void
 
1466
maybe_emit_changed_now (UDisksClient *client)
 
1467
{
 
1468
  if (client->changed_timeout_source == NULL)
 
1469
    goto out;
 
1470
 
 
1471
  g_source_destroy (client->changed_timeout_source);
 
1472
  client->changed_timeout_source = NULL;
 
1473
 
 
1474
  g_signal_emit (client, signals[CHANGED_SIGNAL], 0);
 
1475
 
 
1476
 out:
 
1477
  ;
 
1478
}
 
1479
 
 
1480
 
 
1481
static gboolean
 
1482
on_changed_timeout (gpointer user_data)
 
1483
{
 
1484
  UDisksClient *client = UDISKS_CLIENT (user_data);
 
1485
  client->changed_timeout_source = NULL;
 
1486
  g_signal_emit (client, signals[CHANGED_SIGNAL], 0);
 
1487
  return FALSE; /* remove source */
 
1488
}
 
1489
 
 
1490
/**
 
1491
 * udisks_client_queue_changed:
 
1492
 * @client: A #UDisksClient.
 
1493
 *
 
1494
 * Queues up a #UDisksClient::changed signal and rate-limit it. See
 
1495
 * the documentation for the #UDisksClient::changed property for more
 
1496
 * information.
 
1497
 *
 
1498
 * Since: 2.1
 
1499
 */
 
1500
void
 
1501
udisks_client_queue_changed (UDisksClient *client)
 
1502
{
 
1503
  g_return_if_fail (UDISKS_IS_CLIENT (client));
 
1504
 
 
1505
  if (client->changed_timeout_source != NULL)
 
1506
    goto out;
 
1507
 
 
1508
  client->changed_timeout_source = g_timeout_source_new (100);
 
1509
  g_source_set_callback (client->changed_timeout_source,
 
1510
                         (GSourceFunc) on_changed_timeout,
 
1511
                         client,
 
1512
                         NULL); /* destroy notify */
 
1513
  g_source_attach (client->changed_timeout_source, client->context);
 
1514
  g_source_unref (client->changed_timeout_source);
 
1515
 
 
1516
 out:
 
1517
  ;
 
1518
}
 
1519
 
 
1520
static void
 
1521
on_object_added (GDBusObjectManager  *manager,
 
1522
                 GDBusObject         *object,
 
1523
                 gpointer             user_data)
 
1524
{
 
1525
  UDisksClient *client = UDISKS_CLIENT (user_data);
 
1526
  GList *interfaces, *l;
 
1527
 
 
1528
  interfaces = g_dbus_object_get_interfaces (object);
 
1529
  for (l = interfaces; l != NULL; l = l->next)
 
1530
    {
 
1531
      init_interface_proxy (client, G_DBUS_PROXY (l->data));
 
1532
    }
 
1533
  g_list_foreach (interfaces, (GFunc) g_object_unref, NULL);
 
1534
  g_list_free (interfaces);
 
1535
 
 
1536
  udisks_client_queue_changed (client);
 
1537
}
 
1538
 
 
1539
static void
 
1540
on_object_removed (GDBusObjectManager  *manager,
 
1541
                   GDBusObject         *object,
 
1542
                   gpointer             user_data)
 
1543
{
 
1544
  UDisksClient *client = UDISKS_CLIENT (user_data);
 
1545
  udisks_client_queue_changed (client);
 
1546
}
 
1547
 
 
1548
static void
 
1549
init_interface_proxy (UDisksClient *client,
 
1550
                      GDBusProxy   *proxy)
 
1551
{
 
1552
  /* disable method timeouts */
 
1553
  g_dbus_proxy_set_default_timeout (proxy, G_MAXINT);
 
1554
}
 
1555
 
 
1556
static void
 
1557
on_interface_added (GDBusObjectManager  *manager,
 
1558
                    GDBusObject         *object,
 
1559
                    GDBusInterface      *interface,
 
1560
                    gpointer             user_data)
 
1561
{
 
1562
  UDisksClient *client = UDISKS_CLIENT (user_data);
 
1563
 
 
1564
  init_interface_proxy (client, G_DBUS_PROXY (interface));
 
1565
 
 
1566
  udisks_client_queue_changed (client);
 
1567
}
 
1568
 
 
1569
static void
 
1570
on_interface_removed (GDBusObjectManager  *manager,
 
1571
                      GDBusObject         *object,
 
1572
                      GDBusInterface      *interface,
 
1573
                      gpointer             user_data)
 
1574
{
 
1575
  UDisksClient *client = UDISKS_CLIENT (user_data);
 
1576
  udisks_client_queue_changed (client);
 
1577
}
 
1578
 
 
1579
static void
 
1580
on_interface_proxy_properties_changed (GDBusObjectManagerClient   *manager,
 
1581
                                       GDBusObjectProxy           *object_proxy,
 
1582
                                       GDBusProxy                 *interface_proxy,
 
1583
                                       GVariant                   *changed_properties,
 
1584
                                       const gchar *const         *invalidated_properties,
 
1585
                                       gpointer                    user_data)
 
1586
{
 
1587
  UDisksClient *client = UDISKS_CLIENT (user_data);
 
1588
  udisks_client_queue_changed (client);
 
1589
}
 
1590
 
 
1591
/* ---------------------------------------------------------------------------------------------------- */
 
1592
 
 
1593
#define KILOBYTE_FACTOR 1000.0
 
1594
#define MEGABYTE_FACTOR (1000.0 * 1000.0)
 
1595
#define GIGABYTE_FACTOR (1000.0 * 1000.0 * 1000.0)
 
1596
#define TERABYTE_FACTOR (1000.0 * 1000.0 * 1000.0 * 1000.0)
 
1597
 
 
1598
#define KIBIBYTE_FACTOR 1024.0
 
1599
#define MEBIBYTE_FACTOR (1024.0 * 1024.0)
 
1600
#define GIBIBYTE_FACTOR (1024.0 * 1024.0 * 1024.0)
 
1601
#define TEBIBYTE_FACTOR (1024.0 * 1024.0 * 1024.0 * 10242.0)
 
1602
 
 
1603
static char *
 
1604
get_pow2_size (guint64 size)
 
1605
{
 
1606
  gchar *str;
 
1607
  gdouble displayed_size;
 
1608
  const gchar *unit;
 
1609
  guint digits;
 
1610
 
 
1611
  if (size < MEBIBYTE_FACTOR)
 
1612
    {
 
1613
      displayed_size = (double) size / KIBIBYTE_FACTOR;
 
1614
      unit = "KiB";
 
1615
    }
 
1616
  else if (size < GIBIBYTE_FACTOR)
 
1617
    {
 
1618
      displayed_size = (double) size / MEBIBYTE_FACTOR;
 
1619
      unit = "MiB";
 
1620
    }
 
1621
  else if (size < TEBIBYTE_FACTOR)
 
1622
    {
 
1623
      displayed_size = (double) size / GIBIBYTE_FACTOR;
 
1624
      unit = "GiB";
 
1625
    }
 
1626
  else
 
1627
    {
 
1628
      displayed_size = (double) size / TEBIBYTE_FACTOR;
 
1629
      unit = "TiB";
 
1630
    }
 
1631
 
 
1632
  if (displayed_size < 10.0)
 
1633
    digits = 1;
 
1634
  else
 
1635
    digits = 0;
 
1636
 
 
1637
  str = g_strdup_printf ("%.*f %s", digits, displayed_size, unit);
 
1638
 
 
1639
  return str;
 
1640
}
 
1641
 
 
1642
static char *
 
1643
get_pow10_size (guint64 size)
 
1644
{
 
1645
  gchar *str;
 
1646
  gdouble displayed_size;
 
1647
  const gchar *unit;
 
1648
  guint digits;
 
1649
 
 
1650
  if (size < MEGABYTE_FACTOR)
 
1651
    {
 
1652
      displayed_size = (double) size / KILOBYTE_FACTOR;
 
1653
      unit = "KB";
 
1654
    }
 
1655
  else if (size < GIGABYTE_FACTOR)
 
1656
    {
 
1657
      displayed_size = (double) size / MEGABYTE_FACTOR;
 
1658
      unit = "MB";
 
1659
    }
 
1660
  else if (size < TERABYTE_FACTOR)
 
1661
    {
 
1662
      displayed_size = (double) size / GIGABYTE_FACTOR;
 
1663
      unit = "GB";
 
1664
    }
 
1665
  else
 
1666
    {
 
1667
      displayed_size = (double) size / TERABYTE_FACTOR;
 
1668
      unit = "TB";
 
1669
    }
 
1670
 
 
1671
  if (displayed_size < 10.0)
 
1672
    digits = 1;
 
1673
  else
 
1674
    digits = 0;
 
1675
 
 
1676
  str = g_strdup_printf ("%.*f %s", digits, displayed_size, unit);
 
1677
 
 
1678
  return str;
 
1679
}
 
1680
 
 
1681
/**
 
1682
 * udisks_client_get_size_for_display:
 
1683
 * @client: A #UDisksClient.
 
1684
 * @size: Size in bytes
 
1685
 * @use_pow2: Whether power-of-two units should be used instead of power-of-ten units.
 
1686
 * @long_string: Whether to produce a long string.
 
1687
 *
 
1688
 * Utility function to get a human-readable string that represents @size.
 
1689
 *
 
1690
 * Returns: A string that should be freed with g_free().
 
1691
 */
 
1692
gchar *
 
1693
udisks_client_get_size_for_display (UDisksClient  *client,
 
1694
                                    guint64        size,
 
1695
                                    gboolean       use_pow2,
 
1696
                                    gboolean       long_string)
 
1697
{
 
1698
  gchar *str;
 
1699
 
 
1700
  if (long_string)
 
1701
    {
 
1702
      gchar *size_str;
 
1703
      size_str = g_strdup_printf ("%'" G_GINT64_FORMAT, size);
 
1704
      if (use_pow2)
 
1705
        {
 
1706
          gchar *pow2_str;
 
1707
          pow2_str = get_pow2_size (size);
 
1708
          /* Translators: The first %s is the size in power-of-2 units, e.g. '64 KiB'
 
1709
           * the second %s is the size as a number e.g. '65,536' (always > 1)
 
1710
           */
 
1711
          str = g_strdup_printf (C_("byte-size-pow2", "%s (%s bytes)"), pow2_str, size_str);
 
1712
          g_free (pow2_str);
 
1713
        }
 
1714
      else
 
1715
        {
 
1716
          gchar *pow10_str;
 
1717
          pow10_str = get_pow10_size (size);
 
1718
          /* Translators: The first %s is the size in power-of-10 units, e.g. '100 kB'
 
1719
           * the second %s is the size as a number e.g. '100,000' (always > 1)
 
1720
           */
 
1721
          str = g_strdup_printf (C_("byte-size-pow10", "%s (%s bytes)"), pow10_str, size_str);
 
1722
          g_free (pow10_str);
 
1723
        }
 
1724
 
 
1725
      g_free (size_str);
 
1726
    }
 
1727
  else
 
1728
    {
 
1729
      if (use_pow2)
 
1730
        {
 
1731
          str = get_pow2_size (size);
 
1732
        }
 
1733
      else
 
1734
        {
 
1735
          str = get_pow10_size (size);
 
1736
        }
 
1737
    }
 
1738
  return str;
 
1739
}
 
1740
 
 
1741
/* ---------------------------------------------------------------------------------------------------- */
 
1742
 
 
1743
/**
 
1744
 * udisks_client_get_media_compat_for_display:
 
1745
 * @client: A #UDisksClient.
 
1746
 * @media_compat: An array of media types.
 
1747
 *
 
1748
 * Gets a human-readable string of the media described by
 
1749
 * @media_compat. The returned information is localized.
 
1750
 *
 
1751
 * Returns: A string that should be freed with g_free() or %NULL if
 
1752
 * unknown.
 
1753
 */
 
1754
gchar *
 
1755
udisks_client_get_media_compat_for_display (UDisksClient       *client,
 
1756
                                            const gchar* const *media_compat)
 
1757
{
 
1758
  guint n;
 
1759
  gboolean optical_cd;
 
1760
  gboolean optical_dvd;
 
1761
  gboolean optical_bd;
 
1762
  gboolean optical_hddvd;
 
1763
  GString *result;
 
1764
 
 
1765
  optical_cd = FALSE;
 
1766
  optical_dvd = FALSE;
 
1767
  optical_bd = FALSE;
 
1768
  optical_hddvd = FALSE;
 
1769
 
 
1770
  result = g_string_new (NULL);
 
1771
 
 
1772
  for (n = 0; media_compat != NULL && media_compat[n] != NULL; n++)
 
1773
    {
 
1774
      const gchar *media_name;
 
1775
      const gchar *media;
 
1776
 
 
1777
      media = media_compat[n];
 
1778
      media_name = NULL;
 
1779
      if (g_strcmp0 (media, "flash_cf") == 0)
 
1780
        {
 
1781
          /* Translators: This word is used to describe the media inserted into a device */
 
1782
          media_name = C_("media", "CompactFlash");
 
1783
        }
 
1784
      else if (g_strcmp0 (media, "flash_ms") == 0)
 
1785
        {
 
1786
          /* Translators: This word is used to describe the media inserted into a device */
 
1787
          media_name = C_("media", "MemoryStick");
 
1788
        }
 
1789
      else if (g_strcmp0 (media, "flash_sm") == 0)
 
1790
        {
 
1791
          /* Translators: This word is used to describe the media inserted into a device */
 
1792
          media_name = C_("media", "SmartMedia");
 
1793
        }
 
1794
      else if (g_strcmp0 (media, "flash_sd") == 0)
 
1795
        {
 
1796
          /* Translators: This word is used to describe the media inserted into a device */
 
1797
          media_name = C_("media", "SecureDigital");
 
1798
        }
 
1799
      else if (g_strcmp0 (media, "flash_sdhc") == 0)
 
1800
        {
 
1801
          /* Translators: This word is used to describe the media inserted into a device */
 
1802
          media_name = C_("media", "SD High Capacity");
 
1803
        }
 
1804
      else if (g_strcmp0 (media, "floppy") == 0)
 
1805
        {
 
1806
          /* Translators: This word is used to describe the media inserted into a device */
 
1807
          media_name = C_("media", "Floppy");
 
1808
        }
 
1809
      else if (g_strcmp0 (media, "floppy_zip") == 0)
 
1810
        {
 
1811
          /* Translators: This word is used to describe the media inserted into a device */
 
1812
          media_name = C_("media", "Zip");
 
1813
        }
 
1814
      else if (g_strcmp0 (media, "floppy_jaz") == 0)
 
1815
        {
 
1816
          /* Translators: This word is used to describe the media inserted into a device */
 
1817
          media_name = C_("media", "Jaz");
 
1818
        }
 
1819
      else if (g_str_has_prefix (media, "flash"))
 
1820
        {
 
1821
          /* Translators: This word is used to describe the media inserted into a device */
 
1822
          media_name = C_("media", "Flash");
 
1823
        }
 
1824
      else if (g_str_has_prefix (media, "optical_cd"))
 
1825
        {
 
1826
          optical_cd = TRUE;
 
1827
        }
 
1828
      else if (g_str_has_prefix (media, "optical_dvd"))
 
1829
        {
 
1830
          optical_dvd = TRUE;
 
1831
        }
 
1832
      else if (g_str_has_prefix (media, "optical_bd"))
 
1833
        {
 
1834
          optical_bd = TRUE;
 
1835
        }
 
1836
      else if (g_str_has_prefix (media, "optical_hddvd"))
 
1837
        {
 
1838
          optical_hddvd = TRUE;
 
1839
        }
 
1840
 
 
1841
      if (media_name != NULL)
 
1842
        {
 
1843
          if (result->len > 0)
 
1844
            g_string_append_c (result, '/');
 
1845
          g_string_append (result, media_name);
 
1846
        }
 
1847
    }
 
1848
 
 
1849
  if (optical_cd)
 
1850
    {
 
1851
      if (result->len > 0)
 
1852
        g_string_append_c (result, '/');
 
1853
      /* Translators: This word is used to describe the optical disc type, it may appear
 
1854
       * in a slash-separated list e.g. 'CD/DVD/Blu-Ray'
 
1855
       */
 
1856
      g_string_append (result, C_("disc-type", "CD"));
 
1857
    }
 
1858
  if (optical_dvd)
 
1859
    {
 
1860
      if (result->len > 0)
 
1861
        g_string_append_c (result, '/');
 
1862
      /* Translators: This word is used to describe the optical disc type, it may appear
 
1863
       * in a slash-separated list e.g. 'CD/DVD/Blu-Ray'
 
1864
       */
 
1865
      g_string_append (result, C_("disc-type", "DVD"));
 
1866
    }
 
1867
  if (optical_bd)
 
1868
    {
 
1869
      if (result->len > 0)
 
1870
        g_string_append_c (result, '/');
 
1871
      /* Translators: This word is used to describe the optical disc type, it may appear
 
1872
       * in a slash-separated list e.g. 'CD/DVD/Blu-Ray'
 
1873
       */
 
1874
      g_string_append (result, C_("disc-type", "Blu-Ray"));
 
1875
    }
 
1876
  if (optical_hddvd)
 
1877
    {
 
1878
      if (result->len > 0)
 
1879
        g_string_append_c (result, '/');
 
1880
      /* Translators: This word is used to describe the optical disc type, it may appear
 
1881
       * in a slash-separated list e.g. 'CD/DVD/Blu-Ray'
 
1882
       */
 
1883
      g_string_append (result, C_("disc-type", "HDDVD"));
 
1884
    }
 
1885
 
 
1886
  if (result->len > 0)
 
1887
    return g_string_free (result, FALSE);
 
1888
 
 
1889
  g_string_free (result, TRUE);
 
1890
  return NULL;
 
1891
}
 
1892
 
 
1893
/* ---------------------------------------------------------------------------------------------------- */
 
1894
 
 
1895
static const struct
 
1896
{
 
1897
  const gchar *usage;
 
1898
  const gchar *type;
 
1899
  const gchar *version;
 
1900
  const gchar *long_name;
 
1901
  const gchar *short_name;
 
1902
} id_type[] =
 
1903
{
 
1904
  {"filesystem", "vfat",              "FAT12", NC_("fs-type", "FAT (12-bit version)"),              NC_("fs-type", "FAT")},
 
1905
  {"filesystem", "vfat",              "FAT16", NC_("fs-type", "FAT (16-bit version)"),              NC_("fs-type", "FAT")},
 
1906
  {"filesystem", "vfat",              "FAT32", NC_("fs-type", "FAT (32-bit version)"),              NC_("fs-type", "FAT")},
 
1907
  {"filesystem", "ntfs",              "*",     NC_("fs-type", "FAT (version %s)"),                  NC_("fs-type", "FAT")},
 
1908
  {"filesystem", "vfat",              NULL,    NC_("fs-type", "FAT"),                               NC_("fs-type", "FAT")},
 
1909
  {"filesystem", "ntfs",              "*",     NC_("fs-type", "NTFS (version %s)"),                 NC_("fs-type", "NTFS")},
 
1910
  {"filesystem", "ntfs",              NULL,    NC_("fs-type", "NTFS"),                              NC_("fs-type", "NTFS")},
 
1911
  {"filesystem", "hfs",               NULL,    NC_("fs-type", "HFS"),                               NC_("fs-type", "HFS")},
 
1912
  {"filesystem", "hfsplus",           NULL,    NC_("fs-type", "HFS+"),                              NC_("fs-type", "HFS+")},
 
1913
  {"filesystem", "ext2",              "*",     NC_("fs-type", "Ext2 (version %s)"),                 NC_("fs-type", "Ext2")},
 
1914
  {"filesystem", "ext2",              NULL,    NC_("fs-type", "Ext2"),                              NC_("fs-type", "Ext2")},
 
1915
  {"filesystem", "ext3",              "*",     NC_("fs-type", "Ext3 (version %s)"),                 NC_("fs-type", "Ext3")},
 
1916
  {"filesystem", "ext3",              NULL,    NC_("fs-type", "Ext3"),                              NC_("fs-type", "Ext3")},
 
1917
  {"filesystem", "ext4",              "*",     NC_("fs-type", "Ext4 (version %s)"),                 NC_("fs-type", "Ext4")},
 
1918
  {"filesystem", "ext4",              NULL,    NC_("fs-type", "Ext4"),                              NC_("fs-type", "Ext4")},
 
1919
  {"filesystem", "jdb",               "*",     NC_("fs-type", "Journal for Ext (version %s)"),      NC_("fs-type", "JDB")},
 
1920
  {"filesystem", "jdb",               "*",     NC_("fs-type", "Journal for Ext"),                   NC_("fs-type", "JDB")},
 
1921
  {"filesystem", "xfs",               "*",     NC_("fs-type", "XFS (version %s)"),                  NC_("fs-type", "XFS")},
 
1922
  {"filesystem", "xfs",               NULL,    NC_("fs-type", "XFS"),                               NC_("fs-type", "XFS")},
 
1923
  /* TODO: No ID_FS_VERSION yet for btrfs... */
 
1924
  {"filesystem", "btrfs",             NULL,    NC_("fs-type", "Btrfs"),                             NC_("fs-type", "Btrfs")},
 
1925
  {"filesystem", "iso9660",           "*",     NC_("fs-type", "ISO 9660 (version %s)"),             NC_("fs-type", "ISO9660")},
 
1926
  {"filesystem", "iso9660",           NULL,    NC_("fs-type", "ISO 9660"),                          NC_("fs-type", "ISO9660")},
 
1927
  {"filesystem", "udf",               "*",     NC_("fs-type", "UDF (version %s)"),                  NC_("fs-type", "UDF")},
 
1928
  {"filesystem", "udf",               NULL,    NC_("fs-type", "UDF"),                               NC_("fs-type", "UDF")},
 
1929
  {"filesystem", "exfat",             NULL,    NC_("fs-type", "exFAT"),                             NC_("fs-type", "exFAT")},
 
1930
  {"filesystem", "exfat",             "*",     NC_("fs-type", "exFAT (version %s)"),                NC_("fs-type", "exFAT")},
 
1931
  {"other",      "swap",              "*",     NC_("fs-type", "Swap (version %s)"),                 NC_("fs-type", "Swap")},
 
1932
  {"other",      "swap",              NULL,    NC_("fs-type", "Swap"),                              NC_("fs-type", "Swap")},
 
1933
  {"raid",       "LVM2_member",       "*",     NC_("fs-type", "LVM2 Physical Volume (%s)"),         NC_("fs-type", "LVM2 PV")},
 
1934
  {"raid",       "LVM2_member",       NULL,    NC_("fs-type", "LVM2 Physical Volume"),              NC_("fs-type", "LVM2 PV")},
 
1935
  {"raid",       "linux_raid_member", "*",     NC_("fs-type", "Linux RAID Member (version %s)"),    NC_("fs-type", "Linux RAID Member")},
 
1936
  {"raid",       "linux_raid_member", NULL,    NC_("fs-type", "Linux RAID Member"),                 NC_("fs-type", "Linux RAID Member")},
 
1937
  {"raid",       "zfs_member",        "*",     NC_("fs-type", "ZFS Device (ZPool version %s)"),     NC_("fs-type", "ZFS (v%s)")},
 
1938
  {"raid",       "zfs_member",        NULL,    NC_("fs-type", "ZFS Device"),                        NC_("fs-type", "ZFS")},
 
1939
  {"raid",       "isw_raid_member",   "*",     NC_("fs-type", "Intel Matrix RAID Member (version %s)"), NC_("fs-type", "IMSM RAID Member (%s)")},
 
1940
  {"raid",       "isw_raid_member",   NULL,    NC_("fs-type", "Intel Matrix RAID Member"),          NC_("fs-type", "IMSM RAID")},
 
1941
  {"crypto",     "crypto_LUKS",       "*",     NC_("fs-type", "LUKS Encryption (version %s)"),      NC_("fs-type", "LUKS")},
 
1942
  {"crypto",     "crypto_LUKS",       NULL,    NC_("fs-type", "LUKS Encryption"),                   NC_("fs-type", "LUKS")},
 
1943
  {"filesystem", "VMFS",              "*",     NC_("fs-type", "VMFS (version %s)"),                 NC_("fs-type", "VMFS (v%s)")},
 
1944
  {"filesystem", "VMFS",              NULL,    NC_("fs-type", "VMFS"),                              NC_("fs-type", "VMFS")},
 
1945
  {"raid",       "VMFS_volume_member", "*",    NC_("fs-type", "VMFS Volume Member (version %s)"),   NC_("fs-type", "VMFS Member (v%s)")},
 
1946
  {"raid",       "VMFS_volume_member", NULL,   NC_("fs-type", "VMFS Volume Member"),                NC_("fs-type", "VMFS Member")},
 
1947
  {NULL, NULL, NULL, NULL}
 
1948
};
 
1949
 
 
1950
/**
 
1951
 * udisks_client_get_id_for_display:
 
1952
 * @client: A #UDisksClient.
 
1953
 * @usage: Usage id e.g. "filesystem" or "crypto".
 
1954
 * @type: Type e.g. "ext4" or "crypto_LUKS"
 
1955
 * @version: Version.
 
1956
 * @long_string: Whether to produce a long string.
 
1957
 *
 
1958
 * Gets a human readable localized string for @usage, @type and @version.
 
1959
 *
 
1960
 * Returns: A string that should be freed with g_free().
 
1961
 */
 
1962
gchar *
 
1963
udisks_client_get_id_for_display (UDisksClient *client,
 
1964
                                  const gchar  *usage,
 
1965
                                  const gchar  *type,
 
1966
                                  const gchar  *version,
 
1967
                                  gboolean      long_string)
 
1968
{
 
1969
  guint n;
 
1970
  gchar *ret;
 
1971
 
 
1972
  ret = NULL;
 
1973
 
 
1974
  for (n = 0; id_type[n].usage != NULL; n++)
 
1975
    {
 
1976
      if (g_strcmp0 (id_type[n].usage, usage) == 0 &&
 
1977
          g_strcmp0 (id_type[n].type, type) == 0)
 
1978
        {
 
1979
          if ((id_type[n].version == NULL && strlen (version) == 0))
 
1980
            {
 
1981
              if (long_string)
 
1982
                ret = g_strdup (g_dpgettext2 (GETTEXT_PACKAGE, "fs-type", id_type[n].long_name));
 
1983
              else
 
1984
                ret = g_strdup (g_dpgettext2 (GETTEXT_PACKAGE, "fs-type", id_type[n].short_name));
 
1985
              goto out;
 
1986
            }
 
1987
          else if ((g_strcmp0 (id_type[n].version, version) == 0 && strlen (version) > 0) ||
 
1988
                   (g_strcmp0 (id_type[n].version, "*") == 0 && strlen (version) > 0))
 
1989
            {
 
1990
              /* we know better than the compiler here */
 
1991
#ifdef __GNUC_PREREQ
 
1992
# if __GNUC_PREREQ(4,6)
 
1993
#  pragma GCC diagnostic push
 
1994
#  pragma GCC diagnostic ignored "-Wformat-nonliteral"
 
1995
# endif
 
1996
#endif
 
1997
              if (long_string)
 
1998
                ret = g_strdup_printf (g_dpgettext2 (GETTEXT_PACKAGE, "fs-type", id_type[n].long_name), version);
 
1999
              else
 
2000
                ret = g_strdup_printf (g_dpgettext2 (GETTEXT_PACKAGE, "fs-type", id_type[n].short_name), version);
 
2001
              goto out;
 
2002
#ifdef __GNUC_PREREQ
 
2003
# if __GNUC_PREREQ(4,6)
 
2004
#  pragma GCC diagnostic pop
 
2005
# endif
 
2006
#endif
 
2007
            }
 
2008
        }
 
2009
    }
 
2010
 
 
2011
  if (long_string)
 
2012
    {
 
2013
      if (strlen (version) > 0)
 
2014
        {
 
2015
          /* Translators: Shown for unknown filesystem types.
 
2016
           * First %s is the raw filesystem type obtained from udev, second %s is version.
 
2017
           */
 
2018
          ret = g_strdup_printf (C_("fs-type", "Unknown (%s %s)"), type, version);
 
2019
        }
 
2020
      else
 
2021
        {
 
2022
          if (strlen (type) > 0)
 
2023
            {
 
2024
              /* Translators: Shown for unknown filesystem types.
 
2025
               * First %s is the raw filesystem type obtained from udev.
 
2026
               */
 
2027
              ret = g_strdup_printf (C_("fs-type", "Unknown (%s)"), type);
 
2028
            }
 
2029
          else
 
2030
            {
 
2031
              /* Translators: Shown for unknown filesystem types.
 
2032
               */
 
2033
              ret = g_strdup (C_("fs-type", "Unknown"));
 
2034
            }
 
2035
        }
 
2036
    }
 
2037
  else
 
2038
    {
 
2039
      if (strlen (type) > 0)
 
2040
        {
 
2041
          ret = g_strdup (type);
 
2042
        }
 
2043
      else
 
2044
        {
 
2045
          /* Translators: Shown for unknown filesystem types.
 
2046
           */
 
2047
          ret = g_strdup (C_("fs-type", "Unknown"));
 
2048
        }
 
2049
    }
 
2050
 
 
2051
 out:
 
2052
  return ret;
 
2053
}
 
2054
 
 
2055
/* ---------------------------------------------------------------------------------------------------- */
 
2056
 
 
2057
static const struct
 
2058
{
 
2059
  const gchar *type;
 
2060
  const gchar *name;
 
2061
} known_partition_table_types[] =
 
2062
{
 
2063
  /* Translators: name of partition table format */
 
2064
  {"dos", N_("Master Boot Record")},
 
2065
  /* Translators: name of partition table format */
 
2066
  {"gpt", N_("GUID Partition Table")},
 
2067
  /* Translators: name of partition table format */
 
2068
  {"apm", N_("Apple Partition Map")},
 
2069
  {NULL, NULL}
 
2070
};
 
2071
 
 
2072
/**
 
2073
 * udisks_client_get_partition_table_type_for_display:
 
2074
 * @client: A #UDisksClient.
 
2075
 * @partition_table_type: A partition table type e.g. 'dos' or 'gpt'.
 
2076
 *
 
2077
 * Gets a human readable localized string for @partition_table_type.
 
2078
 *
 
2079
 * Returns: A description of @partition_table_type or %NULL.
 
2080
 */
 
2081
const gchar *
 
2082
udisks_client_get_partition_table_type_for_display (UDisksClient  *client,
 
2083
                                                    const gchar   *partition_table_type)
 
2084
{
 
2085
  const gchar *ret = NULL;
 
2086
  guint n;
 
2087
 
 
2088
  for (n = 0; known_partition_table_types[n].type != NULL; n++)
 
2089
    {
 
2090
      if (g_strcmp0 (known_partition_table_types[n].type, partition_table_type) == 0)
 
2091
        {
 
2092
          ret = _(known_partition_table_types[n].name);
 
2093
          goto out;
 
2094
        }
 
2095
    }
 
2096
 
 
2097
 out:
 
2098
  return ret;
 
2099
}
 
2100
 
 
2101
/* ---------------------------------------------------------------------------------------------------- */
 
2102
 
 
2103
static const struct
 
2104
{
 
2105
  const gchar *type;
 
2106
  const gchar *subtype;
 
2107
  const gchar *name;
 
2108
} known_partition_table_subtypes[] =
 
2109
{
 
2110
  /* Translators: name of partition table format */
 
2111
  {"dos", "generic",   NC_("partition-subtype", "Generic")},
 
2112
  {"dos", "linux",     NC_("partition-subtype", "Linux")},
 
2113
  {"dos", "microsoft", NC_("partition-subtype", "Windows")},
 
2114
  {"dos", "other",     NC_("partition-subtype", "Other")},
 
2115
 
 
2116
  {"gpt", "generic",   NC_("partition-subtype", "Generic")},
 
2117
  {"gpt", "linux",     NC_("partition-subtype", "Linux")},
 
2118
  {"gpt", "microsoft", NC_("partition-subtype", "Windows")},
 
2119
  {"gpt", "apple",     NC_("partition-subtype", "Mac OS X")},
 
2120
  {"gpt", "other",     NC_("partition-subtype", "Other")},
 
2121
 
 
2122
  {"apm", "apple",     NC_("partition-subtype", "Mac OS X")},
 
2123
  {"apm", "microsoft", NC_("partition-subtype", "Windows")},
 
2124
  {NULL, NULL}
 
2125
};
 
2126
 
 
2127
/**
 
2128
 * udisks_client_get_partition_table_subtype_for_display:
 
2129
 * @client: A #UDisksClient.
 
2130
 * @partition_table_type: A partition table type e.g. 'dos' or 'gpt'.
 
2131
 * @partition_table_subtype: A partition table type e.g. 'dos' or 'gpt'.
 
2132
 *
 
2133
 * Gets a human readable localized string for @partition_table_type and @partition_table_subtype.
 
2134
 *
 
2135
 * Returns: A description of @partition_table_type and @partition_table_subtype or %NULL.
 
2136
 */
 
2137
const gchar *
 
2138
udisks_client_get_partition_table_subtype_for_display (UDisksClient  *client,
 
2139
                                                       const gchar   *partition_table_type,
 
2140
                                                       const gchar   *partition_table_subtype)
 
2141
{
 
2142
  const gchar *ret = NULL;
 
2143
  guint n;
 
2144
 
 
2145
  for (n = 0; known_partition_table_subtypes[n].type != NULL; n++)
 
2146
    {
 
2147
      if (g_strcmp0 (known_partition_table_subtypes[n].type,    partition_table_type) == 0 &&
 
2148
          g_strcmp0 (known_partition_table_subtypes[n].subtype, partition_table_subtype) == 0)
 
2149
        {
 
2150
          ret = g_dpgettext2 (GETTEXT_PACKAGE, "partition-subtype", known_partition_table_subtypes[n].name);
 
2151
          goto out;
 
2152
        }
 
2153
    }
 
2154
 
 
2155
 out:
 
2156
  return ret;
 
2157
}
 
2158
 
 
2159
/**
 
2160
 * udisks_client_get_partition_table_subtypes:
 
2161
 * @client: A #UDisksClient.
 
2162
 * @partition_table_type: A partition table type e.g. 'dos' or 'gpt'.
 
2163
 *
 
2164
 * Gets all known subtypes for @partition_table_type.
 
2165
 *
 
2166
 * Returns: (transfer container): A %NULL-terminated array of
 
2167
 * strings. Only the container should be freed with g_free().
 
2168
 */
 
2169
const gchar **
 
2170
udisks_client_get_partition_table_subtypes (UDisksClient   *client,
 
2171
                                            const gchar    *partition_table_type)
 
2172
{
 
2173
  guint n;
 
2174
  GPtrArray *p;
 
2175
 
 
2176
  p = g_ptr_array_new();
 
2177
  for (n = 0; known_partition_table_subtypes[n].type != NULL; n++)
 
2178
    {
 
2179
      if (g_strcmp0 (known_partition_table_subtypes[n].type, partition_table_type) == 0)
 
2180
        {
 
2181
          g_ptr_array_add (p, (gpointer) known_partition_table_subtypes[n].subtype);
 
2182
        }
 
2183
    }
 
2184
  g_ptr_array_add (p, NULL);
 
2185
 
 
2186
  return (const gchar **) g_ptr_array_free (p, FALSE);
 
2187
}
 
2188
 
 
2189
/* ---------------------------------------------------------------------------------------------------- */
 
2190
 
 
2191
/* shorthand */
 
2192
#define F_SWAP   UDISKS_PARTITION_TYPE_INFO_FLAGS_SWAP
 
2193
#define F_RAID   UDISKS_PARTITION_TYPE_INFO_FLAGS_RAID
 
2194
#define F_HIDDEN UDISKS_PARTITION_TYPE_INFO_FLAGS_HIDDEN
 
2195
#define F_CONLY  UDISKS_PARTITION_TYPE_INFO_FLAGS_CREATE_ONLY
 
2196
#define F_SYSTEM UDISKS_PARTITION_TYPE_INFO_FLAGS_SYSTEM
 
2197
 
 
2198
static const struct
 
2199
{
 
2200
  const gchar *table_type;
 
2201
  const gchar *table_subtype;
 
2202
  const gchar *type;
 
2203
  const gchar *name;
 
2204
  UDisksPartitionTypeInfoFlags flags;
 
2205
} known_partition_types[] =
 
2206
{
 
2207
  /* see http://en.wikipedia.org/wiki/GUID_Partition_Table */
 
2208
 
 
2209
  /* Not associated with any OS */
 
2210
  {"gpt", "generic",   "024dee41-33e7-11d3-9d69-0008c781f39f", NC_("part-type", "MBR Partition Scheme"), F_SYSTEM},
 
2211
  {"gpt", "generic",   "c12a7328-f81f-11d2-ba4b-00a0c93ec93b", NC_("part-type", "EFI System"), F_SYSTEM},
 
2212
  {"gpt", "generic",   "21686148-6449-6e6f-744e-656564454649", NC_("part-type", "BIOS Boot"), F_SYSTEM},
 
2213
  {"gpt", "generic",   "6a898cc3-1dd2-11b2-99a6-080020736631", NC_("part-type", "ZFS"), 0},   /* see also Apple, Sol. */
 
2214
  /* Linux */
 
2215
  {"gpt", "linux",     "0fc63daf-8483-4772-8e79-3d69d8477de4", NC_("part-type", "Linux Filesystem"), 0},
 
2216
  {"gpt", "linux",     "a19d880f-05fc-4d3b-a006-743f0f84911e", NC_("part-type", "Linux RAID"), F_RAID},
 
2217
  {"gpt", "linux",     "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f", NC_("part-type", "Linux Swap"), F_SWAP},
 
2218
  {"gpt", "linux",     "e6d6d379-f507-44c2-a23c-238f2a3df928", NC_("part-type", "Linux LVM"), F_RAID},
 
2219
  {"gpt", "linux",     "8da63339-0007-60c0-c436-083ac8230908", NC_("part-type", "Linux Reserved"), 0},
 
2220
  /* Microsoft */
 
2221
  {"gpt", "microsoft", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7", NC_("part-type", "Basic Data"), 0},
 
2222
  {"gpt", "microsoft", "e3c9e316-0b5c-4db8-817d-f92df00215ae", NC_("part-type", "Microsoft Reserved"), 0},
 
2223
  {"gpt", "microsoft", "5808c8aa-7e8f-42e0-85d2-e1e90434cfb3", NC_("part-type", "Microsoft LDM metadata"), 0},
 
2224
  {"gpt", "microsoft", "af9b60a0-1431-4f62-bc68-3311714a69ad", NC_("part-type", "Microsoft LDM data"), 0},
 
2225
  {"gpt", "microsoft", "de94bba4-06d1-4d40-a16a-bfd50179d6ac", NC_("part-type", "Microsoft Windows Recovery Environment"), 0},
 
2226
  /* Apple OS X */
 
2227
  {"gpt", "apple",     "48465300-0000-11aa-aa11-00306543ecac", NC_("part-type", "Apple HFS/HFS+"), 0},
 
2228
  {"gpt", "apple",     "55465300-0000-11aa-aa11-00306543ecac", NC_("part-type", "Apple UFS"), 0},
 
2229
  {"gpt", "apple",     "6a898cc3-1dd2-11b2-99a6-080020736631", NC_("part-type", "Apple ZFS"), 0}, /* same as ZFS */
 
2230
  {"gpt", "apple",     "52414944-0000-11aa-aa11-00306543ecac", NC_("part-type", "Apple RAID"), F_RAID},
 
2231
  {"gpt", "apple",     "52414944-5f4f-11aa-aa11-00306543ecac", NC_("part-type", "Apple RAID (offline)"), F_RAID},
 
2232
  {"gpt", "apple",     "426f6f74-0000-11aa-aa11-00306543ecac", NC_("part-type", "Apple Boot"), F_SYSTEM},
 
2233
  {"gpt", "apple",     "4c616265-6c00-11aa-aa11-00306543ecac", NC_("part-type", "Apple Label"), 0},
 
2234
  {"gpt", "apple",     "5265636f-7665-11aa-aa11-00306543ecac", NC_("part-type", "Apple TV Recovery"), F_SYSTEM},
 
2235
  {"gpt", "apple",     "53746f72-6167-11aa-aa11-00306543ecac", NC_("part-type", "Apple Core Storage"), F_RAID},
 
2236
  /* HP-UX */
 
2237
  {"gpt", "other",     "75894c1e-3aeb-11d3-b7c1-7b03a0000000", NC_("part-type", "HP-UX Data"), 0},
 
2238
  {"gpt", "other",     "e2a1e728-32e3-11d6-a682-7b03a0000000", NC_("part-type", "HP-UX Service"), 0},
 
2239
  /* FreeBSD */
 
2240
  {"gpt", "other",     "83bd6b9d-7f41-11dc-be0b-001560b84f0f", NC_("part-type", "FreeBSD Boot"), 0},
 
2241
  {"gpt", "other",     "516e7cb4-6ecf-11d6-8ff8-00022d09712b", NC_("part-type", "FreeBSD Data"), 0},
 
2242
  {"gpt", "other",     "516e7cb5-6ecf-11d6-8ff8-00022d09712b", NC_("part-type", "FreeBSD Swap"), F_SWAP},
 
2243
  {"gpt", "other",     "516e7cb6-6ecf-11d6-8ff8-00022d09712b", NC_("part-type", "FreeBSD UFS"), 0},
 
2244
  {"gpt", "other",     "516e7cb8-6ecf-11d6-8ff8-00022d09712b", NC_("part-type", "FreeBSD Vinum"), F_RAID},
 
2245
  {"gpt", "other",     "516e7cba-6ecf-11d6-8ff8-00022d09712b", NC_("part-type", "FreeBSD ZFS"), 0},
 
2246
  /* Solaris */
 
2247
  {"gpt", "other",     "6a82cb45-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris Boot"), 0},
 
2248
  {"gpt", "other",     "6a85cf4d-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris Root"), 0},
 
2249
  {"gpt", "other",     "6a87c46f-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris Swap"), F_SWAP},
 
2250
  {"gpt", "other",     "6a8b642b-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris Backup"), 0},
 
2251
  {"gpt", "other",     "6a898cc3-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris /usr"), 0}, /* same as ZFS */
 
2252
  {"gpt", "other",     "6a8ef2e9-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris /var"), 0},
 
2253
  {"gpt", "other",     "6a90ba39-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris /home"), 0},
 
2254
  {"gpt", "other",     "6a9283a5-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris Alternate Sector"), 0},
 
2255
  {"gpt", "other",     "6a945a3b-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris Reserved"), 0},
 
2256
  {"gpt", "other",     "6a9630d1-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris Reserved (2)"), 0},
 
2257
  {"gpt", "other",     "6a980767-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris Reserved (3)"), 0},
 
2258
  {"gpt", "other",     "6a96237f-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris Reserved (4)"), 0},
 
2259
  {"gpt", "other",     "6a8d2ac7-1dd2-11b2-99a6-080020736631", NC_("part-type", "Solaris Reserved (5)"), 0},
 
2260
  /* NetBSD */
 
2261
  {"gpt", "other",     "49f48d32-b10e-11dc-b99b-0019d1879648", NC_("part-type", "NetBSD Swap"), F_SWAP},
 
2262
  {"gpt", "other",     "49f48d5a-b10e-11dc-b99b-0019d1879648", NC_("part-type", "NetBSD FFS"), 0},
 
2263
  {"gpt", "other",     "49f48d82-b10e-11dc-b99b-0019d1879648", NC_("part-type", "NetBSD LFS"), 0},
 
2264
  {"gpt", "other",     "49f48daa-b10e-11dc-b99b-0019d1879648", NC_("part-type", "NetBSD RAID"), F_RAID},
 
2265
  {"gpt", "other",     "2db519c4-b10f-11dc-b99b-0019d1879648", NC_("part-type", "NetBSD Concatenated"), 0},
 
2266
  {"gpt", "other",     "2db519ec-b10f-11dc-b99b-0019d1879648", NC_("part-type", "NetBSD Encrypted"), 0},
 
2267
  /* VMWare, see http://blogs.vmware.com/vsphere/2011/08/vsphere-50-storage-features-part-7-gpt.html */
 
2268
  {"gpt", "other",     "aa31e02a-400f-11db-9590-000c2911d1b8", NC_("part-type", "VMWare VMFS"), 0},
 
2269
  {"gpt", "other",     "9d275380-40ad-11db-bf97-000c2911d1b8", NC_("part-type", "VMWare vmkcore"), 0},
 
2270
  /* ChromeOS, see http://www.chromium.org/chromium-os/chromiumos-design-docs/disk-format */
 
2271
  {"gpt", "other",     "cab6e88e-abf3-4102-a07a-d4bb9be3c1d3", NC_("part-type", "ChromeOS Firmware"), 0},
 
2272
  {"gpt", "other",     "fe3a2a5d-4f32-41a7-b725-accc3285a309", NC_("part-type", "ChromeOS Kernel"), 0},
 
2273
  {"gpt", "other",     "3cb8e202-3b7e-47dd-8a3c-7ff2a13cfcec", NC_("part-type", "ChromeOS Root Filesystem"), 0},
 
2274
  {"gpt", "other",     "2e0a753d-9e48-43b0-8337-b15192cb1b5e", NC_("part-type", "ChromeOS Reserved"), 0},
 
2275
 
 
2276
  /* see http://developer.apple.com/documentation/mac/devices/devices-126.html
 
2277
   *     http://lists.apple.com/archives/Darwin-drivers/2003/May/msg00021.html */
 
2278
  {"apm", "apple",     "Apple_Unix_SVR2", NC_("part-type", "Apple UFS"), 0},
 
2279
  {"apm", "apple",     "Apple_HFS", NC_("part-type", "Apple HFS/HFS"), 0},
 
2280
  {"apm", "apple",     "Apple_partition_map", NC_("part-type", "Apple Partition Map"), 0},
 
2281
  {"apm", "apple",     "Apple_Free", NC_("part-type", "Unused"), 0},
 
2282
  {"apm", "apple",     "Apple_Scratch", NC_("part-type", "Empty"), 0},
 
2283
  {"apm", "apple",     "Apple_Driver", NC_("part-type", "Driver"), 0},
 
2284
  {"apm", "apple",     "Apple_Driver43", NC_("part-type", "Driver 4.3"), 0},
 
2285
  {"apm", "apple",     "Apple_PRODOS", NC_("part-type", "ProDOS file system"), 0},
 
2286
  {"apm", "microsoft", "DOS_FAT_12", NC_("part-type", "FAT 12"), 0},
 
2287
  {"apm", "microsoft", "DOS_FAT_16", NC_("part-type", "FAT 16"), 0},
 
2288
  {"apm", "microsoft", "DOS_FAT_32", NC_("part-type", "FAT 32"), 0},
 
2289
  {"apm", "microsoft", "Windows_FAT_16", NC_("part-type", "FAT 16 (Windows)"), 0},
 
2290
  {"apm", "microsoft", "Windows_FAT_32", NC_("part-type", "FAT 32 (Windows)"), 0},
 
2291
 
 
2292
  /* see http://www.win.tue.nl/~aeb/partitions/partition_types-1.html */
 
2293
  {"dos", "generic",   "0x05",  NC_("part-type", "Extended"), F_CONLY},
 
2294
  {"dos", "generic",   "0xee",  NC_("part-type", "EFI GPT"), F_SYSTEM},
 
2295
  {"dos", "generic",   "0xef",  NC_("part-type", "EFI (FAT-12/16/32)"), F_SYSTEM},
 
2296
  {"dos", "linux",     "0x82",  NC_("part-type", "Linux swap"), F_SWAP},
 
2297
  {"dos", "linux",     "0x83",  NC_("part-type", "Linux"), 0},
 
2298
  {"dos", "linux",     "0x85",  NC_("part-type", "Linux Extended"), F_CONLY},
 
2299
  {"dos", "linux",     "0x8e",  NC_("part-type", "Linux LVM"), F_RAID},
 
2300
  {"dos", "linux",     "0xfd",  NC_("part-type", "Linux RAID auto"), F_RAID},
 
2301
  {"dos", "microsoft", "0x01",  NC_("part-type", "FAT12"), 0},
 
2302
  {"dos", "microsoft", "0x04",  NC_("part-type", "FAT16 <32M"), 0},
 
2303
  {"dos", "microsoft", "0x06",  NC_("part-type", "FAT16"), 0},
 
2304
  {"dos", "microsoft", "0x07",  NC_("part-type", "HPFS/NTFS"), 0},
 
2305
  {"dos", "microsoft", "0x0b",  NC_("part-type", "W95 FAT32"), 0},
 
2306
  {"dos", "microsoft", "0x0c",  NC_("part-type", "W95 FAT32 (LBA)"), 0},
 
2307
  {"dos", "microsoft", "0x0e",  NC_("part-type", "W95 FAT16 (LBA)"), 0},
 
2308
  {"dos", "microsoft", "0x0f",  NC_("part-type", "W95 Ext d (LBA)"), F_CONLY},
 
2309
  {"dos", "microsoft", "0x11",  NC_("part-type", "Hidden FAT12"), F_HIDDEN},
 
2310
  {"dos", "microsoft", "0x14",  NC_("part-type", "Hidden FAT16 <32M"), F_HIDDEN},
 
2311
  {"dos", "microsoft", "0x16",  NC_("part-type", "Hidden FAT16"), F_HIDDEN},
 
2312
  {"dos", "microsoft", "0x17",  NC_("part-type", "Hidden HPFS/NTFS"), F_HIDDEN},
 
2313
  {"dos", "microsoft", "0x1b",  NC_("part-type", "Hidden W95 FAT32"), F_HIDDEN},
 
2314
  {"dos", "microsoft", "0x1c",  NC_("part-type", "Hidden W95 FAT32 (LBA)"), F_HIDDEN},
 
2315
  {"dos", "microsoft", "0x1e",  NC_("part-type", "Hidden W95 FAT16 (LBA)"), F_HIDDEN},
 
2316
  {"dos", "other",     "0x10",  NC_("part-type", "OPUS"), 0},
 
2317
  {"dos", "other",     "0x12",  NC_("part-type", "Compaq diagnostics"), 0},
 
2318
  {"dos", "other",     "0x3c",  NC_("part-type", "PartitionMagic"), 0},
 
2319
  {"dos", "other",     "0x81",  NC_("part-type", "Minix"), 0}, /* cf. http://en.wikipedia.org/wiki/MINIX_file_system */
 
2320
  {"dos", "other",     "0x84",  NC_("part-type", "Hibernation"), 0},
 
2321
  {"dos", "other",     "0xa0",  NC_("part-type", "Hibernation"), 0},
 
2322
  {"dos", "other",     "0xa5",  NC_("part-type", "FreeBSD"), 0},
 
2323
  {"dos", "other",     "0xa6",  NC_("part-type", "OpenBSD"), 0},
 
2324
  {"dos", "other",     "0xa8",  NC_("part-type", "Mac OS X"), 0},
 
2325
  {"dos", "other",     "0xaf",  NC_("part-type", "Mac OS X"), 0},
 
2326
  {"dos", "other",     "0xbe",  NC_("part-type", "Solaris boot"), 0},
 
2327
  {"dos", "other",     "0xbf",  NC_("part-type", "Solaris"), 0},
 
2328
  {"dos", "other",     "0xeb",  NC_("part-type", "BeOS BFS"), 0},
 
2329
  {"dos", "other",     "0xec",  NC_("part-type", "SkyOS SkyFS"), 0},
 
2330
  {NULL,  NULL, NULL}
 
2331
};
 
2332
 
 
2333
/**
 
2334
 * udisks_client_get_partition_type_infos:
 
2335
 * @client: A #UDisksClient.
 
2336
 * @partition_table_type: A partition table type e.g. 'dos' or 'gpt'.
 
2337
 * @partition_table_subtype: (allow-none): A partition table subtype or %NULL to get all known types.
 
2338
 *
 
2339
 * Gets information about all known partition types for @partition_table_type and @partition_table_subtype.
 
2340
 *
 
2341
 * Returns: (transfer full) (element-type UDisksPartitionTypeInfo): A list of
 
2342
 *   #UDisksPartitionTypeInfo instances. The returned list should be freed
 
2343
 *   with g_list_free() after freeing each element with udisks_partition_type_info_free().
 
2344
 */
 
2345
GList *
 
2346
udisks_client_get_partition_type_infos (UDisksClient   *client,
 
2347
                                        const gchar    *partition_table_type,
 
2348
                                        const gchar    *partition_table_subtype)
 
2349
{
 
2350
  GList *ret = NULL;
 
2351
  guint n;
 
2352
 
 
2353
  for (n = 0; known_partition_types[n].name != NULL; n++)
 
2354
    {
 
2355
      if (g_strcmp0 (known_partition_types[n].table_type, partition_table_type) == 0 &&
 
2356
          (partition_table_subtype == NULL ||
 
2357
           g_strcmp0 (known_partition_types[n].table_subtype, partition_table_subtype) == 0))
 
2358
        {
 
2359
          UDisksPartitionTypeInfo *info = udisks_partition_type_info_new ();
 
2360
          info->table_type    = known_partition_types[n].table_type;
 
2361
          info->table_subtype = known_partition_types[n].table_subtype;
 
2362
          info->type          = known_partition_types[n].type;
 
2363
          info->flags         = known_partition_types[n].flags;
 
2364
          ret = g_list_prepend (ret, info);
 
2365
        }
 
2366
    }
 
2367
  ret = g_list_reverse (ret);
 
2368
  return ret;
 
2369
}
 
2370
 
 
2371
/**
 
2372
 * udisks_client_get_partition_type_for_display:
 
2373
 * @client: A #UDisksClient.
 
2374
 * @partition_table_type: A partitioning type e.g. 'dos' or 'gpt'.
 
2375
 * @partition_type: A partition type.
 
2376
 *
 
2377
 * Gets a human readable localized string for @partiton_table_type and @partition_type.
 
2378
 *
 
2379
 * Returns: A description of @partition_type or %NULL if unknown.
 
2380
 */
 
2381
const gchar *
 
2382
udisks_client_get_partition_type_for_display (UDisksClient  *client,
 
2383
                                              const gchar   *partition_table_type,
 
2384
                                              const gchar   *partition_type)
 
2385
{
 
2386
  const gchar *ret = NULL;
 
2387
  guint n;
 
2388
 
 
2389
  for (n = 0; known_partition_types[n].name != NULL; n++)
 
2390
    {
 
2391
      if (g_strcmp0 (known_partition_types[n].table_type, partition_table_type) == 0 &&
 
2392
          g_strcmp0 (known_partition_types[n].type, partition_type) == 0)
 
2393
        {
 
2394
          ret = g_dpgettext2 (GETTEXT_PACKAGE, "part-type", known_partition_types[n].name);
 
2395
          goto out;
 
2396
        }
 
2397
    }
 
2398
 
 
2399
 out:
 
2400
  return ret;
 
2401
}
 
2402
 
 
2403
/**
 
2404
 * udisks_client_get_partition_type_and_subtype_for_display:
 
2405
 * @client: A #UDisksClient.
 
2406
 * @partition_table_type: A partitioning type e.g. 'dos' or 'gpt'.
 
2407
 * @partition_table_subtype: A partitioning subtype or %NULL.
 
2408
 * @partition_type: A partition type.
 
2409
 *
 
2410
 * Like udisks_client_get_partition_type_for_display() but also takes
 
2411
 * the partition table subtype into account, if available. This is
 
2412
 * useful in scenarios where different subtypes is using the same
 
2413
 * partition type.
 
2414
 *
 
2415
 * Returns: A description of @partition_type or %NULL if unknown.
 
2416
 *
 
2417
 * Since: 2.1.1
 
2418
 */
 
2419
const gchar *
 
2420
udisks_client_get_partition_type_and_subtype_for_display (UDisksClient  *client,
 
2421
                                                          const gchar   *partition_table_type,
 
2422
                                                          const gchar   *partition_table_subtype,
 
2423
                                                          const gchar   *partition_type)
 
2424
{
 
2425
  const gchar *ret = NULL;
 
2426
  guint n;
 
2427
 
 
2428
  for (n = 0; known_partition_types[n].name != NULL; n++)
 
2429
    {
 
2430
      if (g_strcmp0 (known_partition_types[n].table_type, partition_table_type) == 0 &&
 
2431
          g_strcmp0 (known_partition_types[n].type, partition_type) == 0)
 
2432
        {
 
2433
          if (partition_table_subtype != NULL &&
 
2434
              g_strcmp0 (known_partition_types[n].table_subtype, partition_table_subtype) != 0)
 
2435
            continue;
 
2436
          ret = g_dpgettext2 (GETTEXT_PACKAGE, "part-type", known_partition_types[n].name);
 
2437
          goto out;
 
2438
        }
 
2439
    }
 
2440
 
 
2441
 out:
 
2442
  return ret;
 
2443
}
 
2444
 
 
2445
/* ---------------------------------------------------------------------------------------------------- */
 
2446
 
 
2447
/**
 
2448
 * udisks_client_get_job_description:
 
2449
 * @client: A #UDisksClient.
 
2450
 * @job: A #UDisksJob.
 
2451
 *
 
2452
 * Gets a human-readable and localized text string describing the
 
2453
 * operation of @job.
 
2454
 *
 
2455
 * For known job types, see the documentation for the
 
2456
 * <link linkend="gdbus-property-org-freedesktop-UDisks2-Job.Operation">Job:Operation</link>
 
2457
 * D-Bus property.
 
2458
 *
 
2459
 * Returns: A string that should be freed with g_free().
 
2460
 */
 
2461
gchar *
 
2462
udisks_client_get_job_description (UDisksClient   *client,
 
2463
                                   UDisksJob      *job)
 
2464
{
 
2465
  static gsize once = 0;
 
2466
  static GHashTable *hash = NULL;
 
2467
  const gchar *operation = NULL;
 
2468
  gchar *ret = NULL;
 
2469
 
 
2470
  g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL);
 
2471
 
 
2472
  if (g_once_init_enter (&once))
 
2473
    {
 
2474
      hash = g_hash_table_new (g_str_hash, g_str_equal);
 
2475
      g_hash_table_insert (hash, (gpointer) "ata-smart-selftest",   (gpointer) C_("job", "SMART self-test"));
 
2476
      g_hash_table_insert (hash, (gpointer) "drive-eject",          (gpointer) C_("job", "Ejecting Medium"));
 
2477
      g_hash_table_insert (hash, (gpointer) "encrypted-unlock",     (gpointer) C_("job", "Unlocking Device"));
 
2478
      g_hash_table_insert (hash, (gpointer) "encrypted-lock",       (gpointer) C_("job", "Locking Device"));
 
2479
      g_hash_table_insert (hash, (gpointer) "encrypted-modify",     (gpointer) C_("job", "Modifying Encrypted Device"));
 
2480
      g_hash_table_insert (hash, (gpointer) "swapspace-start",      (gpointer) C_("job", "Starting Swap Device"));
 
2481
      g_hash_table_insert (hash, (gpointer) "swapspace-stop",       (gpointer) C_("job", "Stopping Swap Device"));
 
2482
      g_hash_table_insert (hash, (gpointer) "filesystem-mount",     (gpointer) C_("job", "Mounting Filesystem"));
 
2483
      g_hash_table_insert (hash, (gpointer) "filesystem-unmount",   (gpointer) C_("job", "Unmounting Filesystem"));
 
2484
      g_hash_table_insert (hash, (gpointer) "filesystem-modify",    (gpointer) C_("job", "Modifying Filesystem"));
 
2485
      g_hash_table_insert (hash, (gpointer) "format-erase",         (gpointer) C_("job", "Erasing Device"));
 
2486
      g_hash_table_insert (hash, (gpointer) "format-mkfs",          (gpointer) C_("job", "Creating Filesystem"));
 
2487
      g_hash_table_insert (hash, (gpointer) "loop-setup",           (gpointer) C_("job", "Setting Up Loop Device"));
 
2488
      g_hash_table_insert (hash, (gpointer) "partition-modify",     (gpointer) C_("job", "Modifying Partition"));
 
2489
      g_hash_table_insert (hash, (gpointer) "partition-delete",     (gpointer) C_("job", "Deleting Partition"));
 
2490
      g_hash_table_insert (hash, (gpointer) "partition-create",     (gpointer) C_("job", "Creating Partition"));
 
2491
      g_hash_table_insert (hash, (gpointer) "cleanup",              (gpointer) C_("job", "Cleaning Up"));
 
2492
      g_hash_table_insert (hash, (gpointer) "ata-secure-erase",     (gpointer) C_("job", "ATA Secure Erase"));
 
2493
      g_hash_table_insert (hash, (gpointer) "ata-enhanced-secure-erase", (gpointer) C_("job", "ATA Enhanced Secure Erase"));
 
2494
      g_hash_table_insert (hash, (gpointer) "md-raid-stop",         (gpointer) C_("job", "Stopping RAID Array"));
 
2495
      g_hash_table_insert (hash, (gpointer) "md-raid-start",        (gpointer) C_("job", "Starting RAID Array"));
 
2496
      g_hash_table_insert (hash, (gpointer) "md-raid-fault-device", (gpointer) C_("job", "Marking Device as Faulty"));
 
2497
      g_hash_table_insert (hash, (gpointer) "md-raid-remove-device",(gpointer) C_("job", "Removing Device from Array"));
 
2498
      g_hash_table_insert (hash, (gpointer) "md-raid-add-device",   (gpointer) C_("job", "Adding Device to Array"));
 
2499
      g_hash_table_insert (hash, (gpointer) "md-raid-set-bitmap",   (gpointer) C_("job", "Setting Write-Intent Bitmap"));
 
2500
      g_hash_table_insert (hash, (gpointer) "md-raid-create",       (gpointer) C_("job", "Creating RAID Array"));
 
2501
      g_once_init_leave (&once, (gsize) 1);
 
2502
    }
 
2503
 
 
2504
  operation = udisks_job_get_operation (job);
 
2505
  if (operation != NULL)
 
2506
    ret = g_strdup (g_hash_table_lookup (hash, operation));
 
2507
  if (ret == NULL)
 
2508
    ret = g_strdup_printf (C_("unknown-job", "Unknown (%s)"), udisks_job_get_operation (job));
 
2509
 
 
2510
  return ret;
 
2511
}
 
2512
 
 
2513
/* ---------------------------------------------------------------------------------------------------- */
 
2514
 
 
2515
static UDisksPartitionTypeInfo *
 
2516
udisks_partition_type_info_new (void)
 
2517
{
 
2518
  UDisksPartitionTypeInfo *ret;
 
2519
  ret = g_slice_new0 (UDisksPartitionTypeInfo);
 
2520
  return ret;
 
2521
}
 
2522
 
 
2523
static UDisksPartitionTypeInfo *
 
2524
udisks_partition_type_info_copy (UDisksPartitionTypeInfo  *info)
 
2525
{
 
2526
  UDisksPartitionTypeInfo *ret;
 
2527
  ret = udisks_partition_type_info_new ();
 
2528
  memcpy (ret, info, sizeof (UDisksPartitionTypeInfo));
 
2529
  return ret;
 
2530
}
 
2531
 
 
2532
/**
 
2533
 * udisks_partition_type_info_free:
 
2534
 * @info: A #UDisksPartitionTypeInfo.
 
2535
 *
 
2536
 * Frees @info.
 
2537
 */
 
2538
void
 
2539
udisks_partition_type_info_free (UDisksPartitionTypeInfo  *info)
 
2540
{
 
2541
  g_slice_free (UDisksPartitionTypeInfo, info);
 
2542
}
 
2543
 
 
2544
G_DEFINE_BOXED_TYPE (UDisksPartitionTypeInfo, udisks_partition_type_info, udisks_partition_type_info_copy, udisks_partition_type_info_free);