gmount.c 30.9 KB
Newer Older
1 2
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */

3 4
/* GIO - GLib Input, Output and Streaming Library
 * 
5
 * Copyright (C) 2006-2008 Red Hat, Inc.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: Alexander Larsson <alexl@redhat.com>
 *         David Zeuthen <davidz@redhat.com>
 */

26
#include "config.h"
27 28 29

#include <string.h>

30 31
#include "gmount.h"
#include "gmountprivate.h"
32
#include "gasyncresult.h"
33
#include "gsimpleasyncresult.h"
34
#include "gioerror.h"
35 36 37 38 39
#include "glibintl.h"


/**
 * SECTION:gmount
40
 * @short_description: Mount management
Matthias Clasen's avatar
Matthias Clasen committed
41
 * @include: gio/gio.h
42
 * @see_also: GVolume, GUnixMountEntry, GUnixMountPoint
43
 *
44 45
 * The #GMount interface represents user-visible mounts. Note, when 
 * porting from GnomeVFS, #GMount is the moral equivalent of #GnomeVFSVolume.
46 47
 *
 * #GMount is a "mounted" filesystem that you can access. Mounted is in
48
 * quotes because it's not the same as a unix mount, it might be a gvfs
49 50
 * mount, but you can still access the files on it if you use GIO. Might or
 * might not be related to a volume object.
51 52
 * 
 * Unmounting a #GMount instance is an asynchronous operation. For
53 54
 * more information about asynchronous operations, see #GAsyncResult
 * and #GSimpleAsyncResult. To unmount a #GMount instance, first call
55
 * g_mount_unmount_with_operation() with (at least) the #GMount instance and a
56 57 58
 * #GAsyncReadyCallback.  The callback will be fired when the
 * operation has resolved (either with success or failure), and a
 * #GAsyncReady structure will be passed to the callback.  That
59
 * callback should then call g_mount_unmount_with_operation_finish() with the #GMount
60
 * and the #GAsyncReady data to see if the operation was completed
61
 * successfully.  If an @error is present when g_mount_unmount_with_operation_finish() 
62
 * is called, then it will be filled with any error information.
63 64
 **/

Dan Winship's avatar
Dan Winship committed
65 66
typedef GMountIface GMountInterface;
G_DEFINE_INTERFACE (GMount, g_mount, G_TYPE_OBJECT)
67 68

static void
Dan Winship's avatar
Dan Winship committed
69
g_mount_default_init (GMountInterface *iface)
70
{
Dan Winship's avatar
Dan Winship committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
  /**
   * GMount::changed:
   * @mount: the object on which the signal is emitted
   *
   * Emitted when the mount has been changed.
   **/
  g_signal_new (I_("changed"),
                G_TYPE_MOUNT,
                G_SIGNAL_RUN_LAST,
                G_STRUCT_OFFSET (GMountIface, changed),
                NULL, NULL,
                g_cclosure_marshal_VOID__VOID,
                G_TYPE_NONE, 0);

  /**
   * GMount::unmounted:
   * @mount: the object on which the signal is emitted
   *
   * This signal is emitted when the #GMount have been
   * unmounted. If the recipient is holding references to the
   * object they should release them so the object can be
   * finalized.
   **/
  g_signal_new (I_("unmounted"),
                G_TYPE_MOUNT,
                G_SIGNAL_RUN_LAST,
                G_STRUCT_OFFSET (GMountIface, unmounted),
                NULL, NULL,
                g_cclosure_marshal_VOID__VOID,
                G_TYPE_NONE, 0);
  /**
   * GMount::pre-unmount:
   * @mount: the object on which the signal is emitted
   *
   * This signal is emitted when the #GMount is about to be
   * unmounted.
   *
   * Since: 2.22
   **/
  g_signal_new (I_("pre-unmount"),
                G_TYPE_MOUNT,
                G_SIGNAL_RUN_LAST,
                G_STRUCT_OFFSET (GMountIface, pre_unmount),
                NULL, NULL,
                g_cclosure_marshal_VOID__VOID,
                G_TYPE_NONE, 0);
117 118 119 120 121 122 123 124
}

/**
 * g_mount_get_root:
 * @mount: a #GMount.
 * 
 * Gets the root directory on @mount.
 * 
125
 * Returns: (transfer full): a #GFile. 
126 127
 *      The returned object should be unreffed with 
 *      g_object_unref() when no longer needed.
128 129 130 131 132 133 134 135 136 137 138 139 140
 **/
GFile *
g_mount_get_root (GMount *mount)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);

  iface = G_MOUNT_GET_IFACE (mount);

  return (* iface->get_root) (mount);
}

141 142 143 144 145 146 147 148
/**
 * g_mount_get_default_location:
 * @mount: a #GMount.
 *
 * Gets the default location of @mount. The default location of the given
 * @mount is a path that reflects the main entry point for the user (e.g.
 * the home directory, or the root of the volume).
 *
149
 * Returns: (transfer full): a #GFile.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
 *      The returned object should be unreffed with
 *      g_object_unref() when no longer needed.
 **/
GFile *
g_mount_get_default_location (GMount *mount)
{
  GMountIface *iface;
  GFile       *file;

  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);

  iface = G_MOUNT_GET_IFACE (mount);
  
  /* Fallback to get_root when default_location () is not available */
  if (iface->get_default_location)
    file = (* iface->get_default_location) (mount);
  else
    file = (* iface->get_root) (mount);

  return file;
}

172 173 174 175 176 177
/**
 * g_mount_get_name:
 * @mount: a #GMount.
 * 
 * Gets the name of @mount.
 * 
178 179 180
 * Returns: the name for the given @mount. 
 *     The returned string should be freed with g_free()
 *     when no longer needed.
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
 **/
char *
g_mount_get_name (GMount *mount)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);

  iface = G_MOUNT_GET_IFACE (mount);

  return (* iface->get_name) (mount);
}

/**
 * g_mount_get_icon:
 * @mount: a #GMount.
 * 
 * Gets the icon for @mount.
 * 
200
 * Returns: (transfer full): a #GIcon.
201 202
 *      The returned object should be unreffed with 
 *      g_object_unref() when no longer needed.
203 204 205 206 207 208 209 210 211 212 213 214
 **/
GIcon *
g_mount_get_icon (GMount *mount)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);

  iface = G_MOUNT_GET_IFACE (mount);

  return (* iface->get_icon) (mount);
}
215 216 217 218 219 220 221 222 223 224 225

/**
 * g_mount_get_uuid:
 * @mount: a #GMount.
 * 
 * Gets the UUID for the @mount. The reference is typically based on
 * the file system UUID for the mount in question and should be
 * considered an opaque string. Returns %NULL if there is no UUID
 * available.
 * 
 * Returns: the UUID for @mount or %NULL if no UUID can be computed.
226 227
 *     The returned string should be freed with g_free()
 *     when no longer needed.
228 229 230 231 232 233 234 235 236 237 238 239 240
 **/
char *
g_mount_get_uuid (GMount *mount)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);

  iface = G_MOUNT_GET_IFACE (mount);

  return (* iface->get_uuid) (mount);
}

241 242 243 244 245 246
/**
 * g_mount_get_volume:
 * @mount: a #GMount.
 * 
 * Gets the volume for the @mount.
 * 
247
 * Returns: (transfer full): a #GVolume or %NULL if @mount is not associated with a volume.
248 249
 *      The returned object should be unreffed with 
 *      g_object_unref() when no longer needed.
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
 **/
GVolume *
g_mount_get_volume (GMount *mount)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);

  iface = G_MOUNT_GET_IFACE (mount);

  return (* iface->get_volume) (mount);
}

/**
 * g_mount_get_drive:
 * @mount: a #GMount.
 * 
 * Gets the drive for the @mount.
 *
 * This is a convenience method for getting the #GVolume and then
 * using that object to get the #GDrive.
 * 
272
 * Returns: (transfer full): a #GDrive or %NULL if @mount is not associated with a volume or a drive.
273 274
 *      The returned object should be unreffed with 
 *      g_object_unref() when no longer needed.
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
 **/
GDrive *
g_mount_get_drive (GMount *mount)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);

  iface = G_MOUNT_GET_IFACE (mount);

  return (* iface->get_drive) (mount);
}

/**
 * g_mount_can_unmount: 
 * @mount: a #GMount.
 * 
 * Checks if @mount can be mounted.
 * 
 * Returns: %TRUE if the @mount can be unmounted.
 **/
gboolean
g_mount_can_unmount (GMount *mount)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);

  iface = G_MOUNT_GET_IFACE (mount);

  return (* iface->can_unmount) (mount);
}

308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
/**
 * g_mount_can_eject: 
 * @mount: a #GMount.
 * 
 * Checks if @mount can be eject.
 * 
 * Returns: %TRUE if the @mount can be ejected.
 **/
gboolean
g_mount_can_eject (GMount *mount)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);

  iface = G_MOUNT_GET_IFACE (mount);

  return (* iface->can_eject) (mount);
}

328 329 330
/**
 * g_mount_unmount:
 * @mount: a #GMount.
331
 * @flags: flags affecting the operation
332 333
 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
 * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
334 335 336 337
 * @user_data: user data passed to @callback.
 * 
 * Unmounts a mount. This is an asynchronous operation, and is 
 * finished by calling g_mount_unmount_finish() with the @mount 
338
 * and #GAsyncResult data returned in the @callback.
339 340
 *
 * Deprecated: 2.22: Use g_mount_unmount_with_operation() instead.
341 342
 **/
void
343 344 345 346 347
g_mount_unmount (GMount              *mount,
                 GMountUnmountFlags   flags,
                 GCancellable        *cancellable,
                 GAsyncReadyCallback  callback,
                 gpointer             user_data)
348 349 350 351 352 353 354 355 356 357 358 359
{
  GMountIface *iface;

  g_return_if_fail (G_IS_MOUNT (mount));
  
  iface = G_MOUNT_GET_IFACE (mount);

  if (iface->unmount == NULL)
    {
      g_simple_async_report_error_in_idle (G_OBJECT (mount),
					   callback, user_data,
					   G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
360 361 362
					   /* Translators: This is an error
					    * message for mount objects that
					    * don't implement unmount. */
363
					   _("mount doesn't implement \"unmount\""));
364

365 366 367
      return;
    }
  
368
  (* iface->unmount) (mount, flags, cancellable, callback, user_data);
369 370 371 372 373 374
}

/**
 * g_mount_unmount_finish:
 * @mount: a #GMount.
 * @result: a #GAsyncResult.
Matthias Clasen's avatar
Matthias Clasen committed
375
 * @error: a #GError location to store the error occurring, or %NULL to 
Matthias Clasen's avatar
Matthias Clasen committed
376
 *     ignore.
377
 * 
378
 * Finishes unmounting a mount. If any errors occurred during the operation, 
379 380 381
 * @error will be set to contain the errors and %FALSE will be returned.
 * 
 * Returns: %TRUE if the mount was successfully unmounted. %FALSE otherwise.
382 383
 *
 * Deprecated: 2.22: Use g_mount_unmount_with_operation_finish() instead.
384 385
 **/
gboolean
386
g_mount_unmount_finish (GMount        *mount,
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
                        GAsyncResult  *result,
                        GError       **error)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);

  if (G_IS_SIMPLE_ASYNC_RESULT (result))
    {
      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
      if (g_simple_async_result_propagate_error (simple, error))
        return FALSE;
    }
  
  iface = G_MOUNT_GET_IFACE (mount);
  return (* iface->unmount_finish) (mount, result, error);
}

406 407 408 409

/**
 * g_mount_eject:
 * @mount: a #GMount.
410
 * @flags: flags affecting the unmount if required for eject
411 412
 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
 * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
413 414 415 416
 * @user_data: user data passed to @callback.
 * 
 * Ejects a mount. This is an asynchronous operation, and is 
 * finished by calling g_mount_eject_finish() with the @mount 
417
 * and #GAsyncResult data returned in the @callback.
418 419
 *
 * Deprecated: 2.22: Use g_mount_eject_with_operation() instead.
420 421
 **/
void
422 423 424 425 426
g_mount_eject (GMount              *mount,
               GMountUnmountFlags   flags,
               GCancellable        *cancellable,
               GAsyncReadyCallback  callback,
               gpointer             user_data)
427 428 429 430 431 432 433 434 435 436 437 438
{
  GMountIface *iface;

  g_return_if_fail (G_IS_MOUNT (mount));
  
  iface = G_MOUNT_GET_IFACE (mount);

  if (iface->eject == NULL)
    {
      g_simple_async_report_error_in_idle (G_OBJECT (mount),
					   callback, user_data,
					   G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
439 440 441
					   /* Translators: This is an error
					    * message for mount objects that
					    * don't implement eject. */
442
					   _("mount doesn't implement \"eject\""));
443 444 445 446
      
      return;
    }
  
447
  (* iface->eject) (mount, flags, cancellable, callback, user_data);
448 449 450 451 452 453
}

/**
 * g_mount_eject_finish:
 * @mount: a #GMount.
 * @result: a #GAsyncResult.
Matthias Clasen's avatar
Matthias Clasen committed
454
 * @error: a #GError location to store the error occurring, or %NULL to 
Matthias Clasen's avatar
Matthias Clasen committed
455
 *     ignore.
456
 * 
457
 * Finishes ejecting a mount. If any errors occurred during the operation, 
458 459 460
 * @error will be set to contain the errors and %FALSE will be returned.
 * 
 * Returns: %TRUE if the mount was successfully ejected. %FALSE otherwise.
461 462
 *
 * Deprecated: 2.22: Use g_mount_eject_with_operation_finish() instead.
463 464
 **/
gboolean
465
g_mount_eject_finish (GMount        *mount,
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
                      GAsyncResult  *result,
                      GError       **error)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);

  if (G_IS_SIMPLE_ASYNC_RESULT (result))
    {
      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
      if (g_simple_async_result_propagate_error (simple, error))
        return FALSE;
    }
  
  iface = G_MOUNT_GET_IFACE (mount);
  return (* iface->eject_finish) (mount, result, error);
}

485 486 487 488
/**
 * g_mount_unmount_with_operation:
 * @mount: a #GMount.
 * @flags: flags affecting the operation
489 490 491 492
 * @mount_operation: (allow-none): a #GMountOperation or %NULL to avoid
 *     user interaction.
 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
 * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
 * @user_data: user data passed to @callback.
 *
 * Unmounts a mount. This is an asynchronous operation, and is
 * finished by calling g_mount_unmount_with_operation_finish() with the @mount 
 * and #GAsyncResult data returned in the @callback.
 *
 * Since: 2.22
 **/
void
g_mount_unmount_with_operation (GMount              *mount,
                                GMountUnmountFlags   flags,
                                GMountOperation     *mount_operation,
                                GCancellable        *cancellable,
                                GAsyncReadyCallback  callback,
                                gpointer             user_data)
{
  GMountIface *iface;

  g_return_if_fail (G_IS_MOUNT (mount));

  iface = G_MOUNT_GET_IFACE (mount);

  if (iface->unmount == NULL && iface->unmount_with_operation == NULL)
    {
      g_simple_async_report_error_in_idle (G_OBJECT (mount),
					   callback, user_data,
					   G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
					   /* Translators: This is an error
					    * message for mount objects that
					    * don't implement any of unmount or unmount_with_operation. */
523
					   _("mount doesn't implement \"unmount\" or \"unmount_with_operation\""));
524 525 526 527 528 529 530 531 532 533 534 535 536 537

      return;
    }

  if (iface->unmount_with_operation != NULL)
    (* iface->unmount_with_operation) (mount, flags, mount_operation, cancellable, callback, user_data);
  else
    (* iface->unmount) (mount, flags, cancellable, callback, user_data);
}

/**
 * g_mount_unmount_with_operation_finish:
 * @mount: a #GMount.
 * @result: a #GAsyncResult.
Matthias Clasen's avatar
Matthias Clasen committed
538
 * @error: a #GError location to store the error occurring, or %NULL to
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
 *     ignore.
 *
 * Finishes unmounting a mount. If any errors occurred during the operation,
 * @error will be set to contain the errors and %FALSE will be returned.
 *
 * Returns: %TRUE if the mount was successfully unmounted. %FALSE otherwise.
 *
 * Since: 2.22
 **/
gboolean
g_mount_unmount_with_operation_finish (GMount        *mount,
                                       GAsyncResult  *result,
                                       GError       **error)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);

  if (G_IS_SIMPLE_ASYNC_RESULT (result))
    {
      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
      if (g_simple_async_result_propagate_error (simple, error))
        return FALSE;
    }

  iface = G_MOUNT_GET_IFACE (mount);
  if (iface->unmount_with_operation_finish != NULL)
    return (* iface->unmount_with_operation_finish) (mount, result, error);
  else
    return (* iface->unmount_finish) (mount, result, error);
}


/**
 * g_mount_eject_with_operation:
 * @mount: a #GMount.
 * @flags: flags affecting the unmount if required for eject
577 578 579 580
 * @mount_operation: (allow-none): a #GMountOperation or %NULL to avoid
 *     user interaction.
 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
 * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
 * @user_data: user data passed to @callback.
 *
 * Ejects a mount. This is an asynchronous operation, and is
 * finished by calling g_mount_eject_with_operation_finish() with the @mount
 * and #GAsyncResult data returned in the @callback.
 *
 * Since: 2.22
 **/
void
g_mount_eject_with_operation (GMount              *mount,
                              GMountUnmountFlags   flags,
                              GMountOperation     *mount_operation,
                              GCancellable        *cancellable,
                              GAsyncReadyCallback  callback,
                              gpointer             user_data)
{
  GMountIface *iface;

  g_return_if_fail (G_IS_MOUNT (mount));

  iface = G_MOUNT_GET_IFACE (mount);

  if (iface->eject == NULL && iface->eject_with_operation == NULL)
    {
      g_simple_async_report_error_in_idle (G_OBJECT (mount),
					   callback, user_data,
					   G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
					   /* Translators: This is an error
					    * message for mount objects that
					    * don't implement any of eject or eject_with_operation. */
611
					   _("mount doesn't implement \"eject\" or \"eject_with_operation\""));
612 613 614 615 616 617 618 619 620 621 622 623 624
      return;
    }

  if (iface->eject_with_operation != NULL)
    (* iface->eject_with_operation) (mount, flags, mount_operation, cancellable, callback, user_data);
  else
    (* iface->eject) (mount, flags, cancellable, callback, user_data);
}

/**
 * g_mount_eject_with_operation_finish:
 * @mount: a #GMount.
 * @result: a #GAsyncResult.
Matthias Clasen's avatar
Matthias Clasen committed
625
 * @error: a #GError location to store the error occurring, or %NULL to
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
 *     ignore.
 *
 * Finishes ejecting a mount. If any errors occurred during the operation,
 * @error will be set to contain the errors and %FALSE will be returned.
 *
 * Returns: %TRUE if the mount was successfully ejected. %FALSE otherwise.
 *
 * Since: 2.22
 **/
gboolean
g_mount_eject_with_operation_finish (GMount        *mount,
                                     GAsyncResult  *result,
                                     GError       **error)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);

  if (G_IS_SIMPLE_ASYNC_RESULT (result))
    {
      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
      if (g_simple_async_result_propagate_error (simple, error))
        return FALSE;
    }

  iface = G_MOUNT_GET_IFACE (mount);
  if (iface->eject_with_operation_finish != NULL)
    return (* iface->eject_with_operation_finish) (mount, result, error);
  else
    return (* iface->eject_finish) (mount, result, error);
}

659 660 661
/**
 * g_mount_remount:
 * @mount: a #GMount.
662
 * @flags: flags affecting the operation
663 664 665 666
 * @mount_operation: (allow-none): a #GMountOperation or %NULL to avoid
 *     user interaction.
 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
 * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
667 668 669
 * @user_data: user data passed to @callback.
 * 
 * Remounts a mount. This is an asynchronous operation, and is 
670
 * finished by calling g_mount_remount_finish() with the @mount 
671 672 673 674 675 676 677 678 679
 * and #GAsyncResults data returned in the @callback.
 *
 * Remounting is useful when some setting affecting the operation
 * of the volume has been changed, as these may need a remount to
 * take affect. While this is semantically equivalent with unmounting
 * and then remounting not all backends might need to actually be
 * unmounted.
 **/
void
680 681 682 683 684 685
g_mount_remount (GMount              *mount,
                 GMountMountFlags     flags,
                 GMountOperation     *mount_operation,
                 GCancellable        *cancellable,
                 GAsyncReadyCallback  callback,
                 gpointer             user_data)
686 687 688 689 690 691 692 693
{
  GMountIface *iface;

  g_return_if_fail (G_IS_MOUNT (mount));
  
  iface = G_MOUNT_GET_IFACE (mount);

  if (iface->remount == NULL)
694
    { 
695
      g_simple_async_report_error_in_idle (G_OBJECT (mount),
696 697
					   callback, user_data,
					   G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
698 699 700
					   /* Translators: This is an error
					    * message for mount objects that
					    * don't implement remount. */
701
					   _("mount doesn't implement \"remount\""));
702 703 704 705
      
      return;
    }
  
706
  (* iface->remount) (mount, flags, mount_operation, cancellable, callback, user_data);
707 708 709 710 711 712
}

/**
 * g_mount_remount_finish:
 * @mount: a #GMount.
 * @result: a #GAsyncResult.
Matthias Clasen's avatar
Matthias Clasen committed
713
 * @error: a #GError location to store the error occurring, or %NULL to 
Matthias Clasen's avatar
Matthias Clasen committed
714
 *     ignore.
715
 * 
716
 * Finishes remounting a mount. If any errors occurred during the operation, 
717 718 719 720 721
 * @error will be set to contain the errors and %FALSE will be returned.
 * 
 * Returns: %TRUE if the mount was successfully remounted. %FALSE otherwise.
 **/
gboolean
722
g_mount_remount_finish (GMount        *mount,
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
                        GAsyncResult  *result,
                        GError       **error)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);

  if (G_IS_SIMPLE_ASYNC_RESULT (result))
    {
      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
      if (g_simple_async_result_propagate_error (simple, error))
        return FALSE;
    }
  
  iface = G_MOUNT_GET_IFACE (mount);
  return (* iface->remount_finish) (mount, result, error);
}

742 743 744 745 746
/**
 * g_mount_guess_content_type:
 * @mount: a #GMount
 * @force_rescan: Whether to force a rescan of the content. 
 *     Otherwise a cached result will be used if available
747
 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
748 749 750 751 752 753 754 755 756
 * @callback: a #GAsyncReadyCallback
 * @user_data: user data passed to @callback
 * 
 * Tries to guess the type of content stored on @mount. Returns one or
 * more textual identifiers of well-known content types (typically
 * prefixed with "x-content/"), e.g. x-content/image-dcf for camera 
 * memory cards. See the <ulink url="http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec">shared-mime-info</ulink>
 * specification for more on x-content types.
 *
757 758 759 760
 * This is an asynchronous operation (see
 * g_mount_guess_content_type_sync() for the synchronous version), and
 * is finished by calling g_mount_guess_content_type_finish() with the
 * @mount and #GAsyncResult data returned in the @callback.
761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796
 *
 * Since: 2.18
 */
void
g_mount_guess_content_type (GMount              *mount,
                            gboolean             force_rescan,
                            GCancellable        *cancellable,
                            GAsyncReadyCallback  callback,
                            gpointer             user_data)
{
  GMountIface *iface;

  g_return_if_fail (G_IS_MOUNT (mount));

  iface = G_MOUNT_GET_IFACE (mount);

  if (iface->guess_content_type == NULL)
    {
      g_simple_async_report_error_in_idle (G_OBJECT (mount),
                                           callback, user_data,
                                           G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                                           /* Translators: This is an error
                                            * message for mount objects that
                                            * don't implement content type guessing. */
                                           _("mount doesn't implement content type guessing"));

      return;
    }
  
  (* iface->guess_content_type) (mount, force_rescan, cancellable, callback, user_data);
}

/**
 * g_mount_guess_content_type_finish:
 * @mount: a #GMount
 * @result: a #GAsyncResult
Matthias Clasen's avatar
Matthias Clasen committed
797
 * @error: a #GError location to store the error occurring, or %NULL to 
798 799
 *     ignore
 * 
Matthias Clasen's avatar
Matthias Clasen committed
800
 * Finishes guessing content types of @mount. If any errors occurred
801 802 803 804 805
 * during the operation, @error will be set to contain the errors and
 * %FALSE will be returned. In particular, you may get an 
 * %G_IO_ERROR_NOT_SUPPORTED if the mount does not support content 
 * guessing.
 * 
806
 * Returns: (transfer full) (element-type utf8): a %NULL-terminated array of content types or %NULL on error. 
807 808 809 810 811 812 813 814 815 816 817
 *     Caller should free this array with g_strfreev() when done with it.
 *
 * Since: 2.18
 **/
gchar **
g_mount_guess_content_type_finish (GMount        *mount,
                                   GAsyncResult  *result,
                                   GError       **error)
{
  GMountIface *iface;

Matthias Clasen's avatar
Matthias Clasen committed
818 819
  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
820 821 822 823 824

  if (G_IS_SIMPLE_ASYNC_RESULT (result))
    {
      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
      if (g_simple_async_result_propagate_error (simple, error))
Matthias Clasen's avatar
Matthias Clasen committed
825
        return NULL;
826 827 828 829 830 831
    }
  
  iface = G_MOUNT_GET_IFACE (mount);
  return (* iface->guess_content_type_finish) (mount, result, error);
}

832 833 834 835 836
/**
 * g_mount_guess_content_type_sync:
 * @mount: a #GMount
 * @force_rescan: Whether to force a rescan of the content.
 *     Otherwise a cached result will be used if available
837
 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
Matthias Clasen's avatar
Matthias Clasen committed
838
 * @error: a #GError location to store the error occurring, or %NULL to
839 840 841 842 843 844 845 846 847 848 849
 *     ignore
 *
 * Tries to guess the type of content stored on @mount. Returns one or
 * more textual identifiers of well-known content types (typically
 * prefixed with "x-content/"), e.g. x-content/image-dcf for camera 
 * memory cards. See the <ulink url="http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec">shared-mime-info</ulink>
 * specification for more on x-content types.
 *
 * This is an synchronous operation and as such may block doing IO;
 * see g_mount_guess_content_type() for the asynchronous version.
 *
850
 * Returns: (transfer full) (element-type utf8): a %NULL-terminated array of content types or %NULL on error.
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
 *     Caller should free this array with g_strfreev() when done with it.
 *
 * Since: 2.18
 */
char **
g_mount_guess_content_type_sync (GMount              *mount,
                                 gboolean             force_rescan,
                                 GCancellable        *cancellable,
                                 GError             **error)
{
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);

  iface = G_MOUNT_GET_IFACE (mount);

  if (iface->guess_content_type_sync == NULL)
    {
      g_set_error_literal (error,
                           G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                           /* Translators: This is an error
                            * message for mount objects that
                            * don't implement content type guessing. */
                           _("mount doesn't implement synchronous content type guessing"));

      return NULL;
    }

  return (* iface->guess_content_type_sync) (mount, force_rescan, cancellable, error);
}
881

882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
G_LOCK_DEFINE_STATIC (priv_lock);

/* only access this structure when holding priv_lock */
typedef struct
{
  gint shadow_ref_count;
} GMountPrivate;

static void
free_private (GMountPrivate *private)
{
  G_LOCK (priv_lock);
  g_free (private);
  G_UNLOCK (priv_lock);
}

/* may only be called when holding priv_lock */
static GMountPrivate *
get_private (GMount *mount)
{
  GMountPrivate *private;

  private = g_object_get_data (G_OBJECT (mount), "g-mount-private");
  if (G_LIKELY (private != NULL))
    goto out;

  private = g_new0 (GMountPrivate, 1);
  g_object_set_data_full (G_OBJECT (mount),
                          "g-mount-private",
                          private,
                          (GDestroyNotify) free_private);

 out:
  return private;
}

/**
 * g_mount_is_shadowed:
 * @mount: A #GMount.
 *
 * Determines if @mount is shadowed. Applications or libraries should
 * avoid displaying @mount in the user interface if it is shadowed.
 *
 * A mount is said to be shadowed if there exists one or more user
 * visible objects (currently #GMount objects) with a root that is
 * inside the root of @mount.
 *
 * One application of shadow mounts is when exposing a single file
 * system that is used to address several logical volumes. In this
 * situation, a #GVolumeMonitor implementation would create two
 * #GVolume objects (for example, one for the camera functionality of
 * the device and one for a SD card reader on the device) with
 * activation URIs <literal>gphoto2://[usb:001,002]/store1/</literal>
 * and <literal>gphoto2://[usb:001,002]/store2/</literal>. When the
 * underlying mount (with root
 * <literal>gphoto2://[usb:001,002]/</literal>) is mounted, said
 * #GVolumeMonitor implementation would create two #GMount objects
 * (each with their root matching the corresponding volume activation
 * root) that would shadow the original mount.
 *
 * The proxy monitor in GVfs 2.26 and later, automatically creates and
 * manage shadow mounts (and shadows the underlying mount) if the
 * activation root on a #GVolume is set.
 *
 * Returns: %TRUE if @mount is shadowed.
 *
 * Since: 2.20
 **/
gboolean
g_mount_is_shadowed (GMount *mount)
{
  GMountPrivate *priv;
  gboolean ret;

  g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);

  G_LOCK (priv_lock);
  priv = get_private (mount);
  ret = (priv->shadow_ref_count > 0);
  G_UNLOCK (priv_lock);

  return ret;
}

/**
 * g_mount_shadow:
 * @mount: A #GMount.
 *
 * Increments the shadow count on @mount. Usually used by
 * #GVolumeMonitor implementations when creating a shadow mount for
 * @mount, see g_mount_is_shadowed() for more information. The caller
 * will need to emit the #GMount::changed signal on @mount manually.
 *
 * Since: 2.20
 **/
void
g_mount_shadow (GMount *mount)
{
  GMountPrivate *priv;

  g_return_if_fail (G_IS_MOUNT (mount));

  G_LOCK (priv_lock);
  priv = get_private (mount);
  priv->shadow_ref_count += 1;
  G_UNLOCK (priv_lock);
}

/**
 * g_mount_unshadow:
 * @mount: A #GMount.
 *
 * Decrements the shadow count on @mount. Usually used by
 * #GVolumeMonitor implementations when destroying a shadow mount for
 * @mount, see g_mount_is_shadowed() for more information. The caller
 * will need to emit the #GMount::changed signal on @mount manually.
 *
 * Since: 2.20
 **/
void
g_mount_unshadow (GMount *mount)
{
  GMountPrivate *priv;

  g_return_if_fail (G_IS_MOUNT (mount));

  G_LOCK (priv_lock);
  priv = get_private (mount);
  priv->shadow_ref_count -= 1;
  if (priv->shadow_ref_count < 0)
    g_warning ("Shadow ref count on GMount is negative");
  G_UNLOCK (priv_lock);
}
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039

/**
 * g_mount_get_sort_key:
 * @mount: A #GMount.
 *
 * Gets the sort key for @mount, if any.
 *
 * Returns: Sorting key for @mount or %NULL if no such key is available.
 *
 * Since: 2.32
 */
const gchar *
g_mount_get_sort_key (GMount  *mount)
{
  const gchar *ret = NULL;
  GMountIface *iface;

  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);

  iface = G_MOUNT_GET_IFACE (mount);
  if (iface->get_sort_key != NULL)
    ret = iface->get_sort_key (mount);

  return ret;
}