1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
3 /* GIO - GLib Input, Output and Streaming Library
5 * Copyright (C) 2006-2007 Red Hat, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20 * Boston, MA 02111-1307, USA.
22 * Author: Alexander Larsson <alexl@redhat.com>
23 * David Zeuthen <davidz@redhat.com>
33 #include "gunixvolume.h"
34 #include "gunixmount.h"
35 #include "gthemedicon.h"
36 #include "gvolumemonitor.h"
37 #include "gsimpleasyncresult.h"
45 GVolumeMonitor *volume_monitor;
46 GUnixMount *mount; /* owned by volume monitor */
56 static void g_unix_volume_volume_iface_init (GVolumeIface *iface);
58 #define g_unix_volume_get_type _g_unix_volume_get_type
59 G_DEFINE_TYPE_WITH_CODE (GUnixVolume, g_unix_volume, G_TYPE_OBJECT,
60 G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME,
61 g_unix_volume_volume_iface_init))
64 g_unix_volume_finalize (GObject *object)
68 volume = G_UNIX_VOLUME (object);
70 if (volume->volume_monitor != NULL)
71 g_object_unref (volume->volume_monitor);
74 _g_unix_mount_unset_volume (volume->mount, volume);
76 g_object_unref (volume->icon);
77 g_free (volume->name);
78 g_free (volume->mount_path);
79 g_free (volume->device_path);
81 if (G_OBJECT_CLASS (g_unix_volume_parent_class)->finalize)
82 (*G_OBJECT_CLASS (g_unix_volume_parent_class)->finalize) (object);
86 g_unix_volume_class_init (GUnixVolumeClass *klass)
88 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
90 gobject_class->finalize = g_unix_volume_finalize;
94 g_unix_volume_init (GUnixVolume *unix_volume)
100 * @volume_monitor: a #GVolumeMonitor.
101 * @mountpoint: a #GUnixMountPoint.
103 * Returns: a #GUnixVolume for the given #GUnixMountPoint.
106 _g_unix_volume_new (GVolumeMonitor *volume_monitor,
107 GUnixMountPoint *mountpoint)
111 if (!(g_unix_mount_point_is_user_mountable (mountpoint) ||
112 g_str_has_prefix (g_unix_mount_point_get_device_path (mountpoint), "/vol/")) ||
113 g_unix_mount_point_is_loopback (mountpoint))
116 volume = g_object_new (G_TYPE_UNIX_VOLUME, NULL);
117 volume->volume_monitor = volume_monitor != NULL ? g_object_ref (volume_monitor) : NULL;
118 volume->mount_path = g_strdup (g_unix_mount_point_get_mount_path (mountpoint));
119 volume->device_path = g_strdup (g_unix_mount_point_get_device_path (mountpoint));
120 volume->can_eject = g_unix_mount_point_guess_can_eject (mountpoint);
122 volume->name = g_unix_mount_point_guess_name (mountpoint);
123 volume->icon = g_unix_mount_point_guess_icon (mountpoint);
128 * g_unix_volume_disconnected:
133 _g_unix_volume_disconnected (GUnixVolume *volume)
137 _g_unix_mount_unset_volume (volume->mount, volume);
138 volume->mount = NULL;
143 * g_unix_volume_set_mount:
149 _g_unix_volume_set_mount (GUnixVolume *volume,
152 if (volume->mount == mount)
156 _g_unix_mount_unset_volume (volume->mount, volume);
158 volume->mount = mount;
160 /* TODO: Emit changed in idle to avoid locking issues */
161 g_signal_emit_by_name (volume, "changed");
162 if (volume->volume_monitor != NULL)
163 g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume);
167 * g_unix_volume_unset_mount:
173 _g_unix_volume_unset_mount (GUnixVolume *volume,
176 if (volume->mount == mount)
178 volume->mount = NULL;
179 /* TODO: Emit changed in idle to avoid locking issues */
180 g_signal_emit_by_name (volume, "changed");
181 if (volume->volume_monitor != NULL)
182 g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume);
187 g_unix_volume_get_icon (GVolume *volume)
189 GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
190 return g_object_ref (unix_volume->icon);
194 g_unix_volume_get_name (GVolume *volume)
196 GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
197 return g_strdup (unix_volume->name);
201 g_unix_volume_get_uuid (GVolume *volume)
207 g_unix_volume_can_mount (GVolume *volume)
213 g_unix_volume_can_eject (GVolume *volume)
215 GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
216 return unix_volume->can_eject;
220 g_unix_volume_get_drive (GVolume *volume)
226 g_unix_volume_get_mount (GVolume *volume)
228 GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
230 if (unix_volume->mount != NULL)
231 return g_object_ref (unix_volume->mount);
238 _g_unix_volume_has_mount_path (GUnixVolume *volume,
239 const char *mount_path)
241 return strcmp (volume->mount_path, mount_path) == 0;
246 GUnixVolume *unix_volume;
247 GAsyncReadyCallback callback;
249 GCancellable *cancellable;
251 GIOChannel *error_channel;
252 guint error_channel_source_id;
253 GString *error_string;
257 eject_mount_cb (GPid pid, gint status, gpointer user_data)
259 EjectMountOp *data = user_data;
260 GSimpleAsyncResult *simple;
262 if (WEXITSTATUS (status) != 0)
265 error = g_error_new_literal (G_IO_ERROR,
267 data->error_string->str);
268 simple = g_simple_async_result_new_from_error (G_OBJECT (data->unix_volume),
272 g_error_free (error);
276 simple = g_simple_async_result_new (G_OBJECT (data->unix_volume),
282 g_simple_async_result_complete (simple);
283 g_object_unref (simple);
285 g_source_remove (data->error_channel_source_id);
286 g_io_channel_unref (data->error_channel);
287 g_string_free (data->error_string, TRUE);
288 close (data->error_fd);
289 g_spawn_close_pid (pid);
294 eject_mount_read_error (GIOChannel *channel,
295 GIOCondition condition,
300 EjectMountOp *data = user_data;
302 g_io_channel_read_to_end (channel, &str, &str_len, NULL);
303 g_string_append (data->error_string, str);
309 eject_mount_do (GVolume *volume,
310 GCancellable *cancellable,
311 GAsyncReadyCallback callback,
315 GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
320 data = g_new0 (EjectMountOp, 1);
321 data->unix_volume = unix_volume;
322 data->callback = callback;
323 data->user_data = user_data;
324 data->cancellable = cancellable;
327 if (!g_spawn_async_with_pipes (NULL, /* working dir */
330 G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH,
331 NULL, /* child_setup */
332 NULL, /* user_data for child_setup */
334 NULL, /* standard_input */
335 NULL, /* standard_output */
338 GSimpleAsyncResult *simple;
339 simple = g_simple_async_result_new_from_error (G_OBJECT (data->unix_volume),
343 g_simple_async_result_complete (simple);
344 g_object_unref (simple);
345 g_error_free (error);
349 data->error_string = g_string_new ("");
350 data->error_channel = g_io_channel_unix_new (data->error_fd);
351 data->error_channel_source_id = g_io_add_watch (data->error_channel, G_IO_IN, eject_mount_read_error, data);
352 g_child_watch_add (child_pid, eject_mount_cb, data);
357 g_unix_volume_mount (GVolume *volume,
358 GMountOperation *mount_operation,
359 GCancellable *cancellable,
360 GAsyncReadyCallback callback,
363 GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
364 char *argv[] = {"mount", NULL, NULL};
366 if (unix_volume->mount_path != NULL)
367 argv[1] = unix_volume->mount_path;
369 argv[1] = unix_volume->device_path;
371 eject_mount_do (volume, cancellable, callback, user_data, argv);
375 g_unix_volume_mount_finish (GVolume *volume,
376 GAsyncResult *result,
383 g_unix_volume_eject (GVolume *volume,
384 GMountUnmountFlags flags,
385 GCancellable *cancellable,
386 GAsyncReadyCallback callback,
389 GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
390 char *argv[] = {"eject", NULL, NULL};
392 argv[1] = unix_volume->device_path;
394 eject_mount_do (volume, cancellable, callback, user_data, argv);
398 g_unix_volume_eject_finish (GVolume *volume,
399 GAsyncResult *result,
406 g_unix_volume_volume_iface_init (GVolumeIface *iface)
408 iface->get_name = g_unix_volume_get_name;
409 iface->get_icon = g_unix_volume_get_icon;
410 iface->get_uuid = g_unix_volume_get_uuid;
411 iface->get_drive = g_unix_volume_get_drive;
412 iface->get_mount = g_unix_volume_get_mount;
413 iface->can_mount = g_unix_volume_can_mount;
414 iface->can_eject = g_unix_volume_can_eject;
415 iface->mount_fn = g_unix_volume_mount;
416 iface->mount_finish = g_unix_volume_mount_finish;
417 iface->eject = g_unix_volume_eject;
418 iface->eject_finish = g_unix_volume_eject_finish;