~psusi/ubuntu/utopic/udisks2/fix-standby

« back to all changes in this revision

Viewing changes to .pc/00git_dev_t_annotation.patch/udisks/udisksclient.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2012-09-20 12:04:46 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20120920120446-bero0m8f04k96yod
Tags: 1.99.0+git20120919-1
* Update to current upstream git head:
  - configure.ac: raise gudev dependency
  - Update list of recovery/system partitions
  - Add support for creating exFAT filesystems and changing exFAT labels
  - Add textual descriptions for IMSM Raid members
  - Use all-caps for RAID in descriptions
  - Lots of test suite robustifications and added tests
  - Enable large file support (LP: #1039022)
  - Mount vfat with "flush" option
* Drop 00git_dev_t_annotation.patch, 00git_testsuite.patch.
* debian/control: Bump libgudev-1.0-dev build dependency as per upstream
  configure.ac.
* debian/udisks2.install: Install umount.udisks2 into /sbin; our old
  util-linux version does not yet find it in /usr/sbin/. (LP: #1019651)

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