~ubuntu-branches/ubuntu/precise/gvfs/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/06_no_crash_on_unmount.patch/daemon/gvfsjobunmount.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2011-11-17 07:43:33 UTC
  • mfrom: (1.1.77) (33.1.18 experimental)
  • Revision ID: package-import@ubuntu.com-20111117074333-ua4kq03btq4shvb1
Tags: 1.10.1-1ubuntu1
* Merge with Debian experimental. Remaining Ubuntu changes:
  - debian/control.in: Drop libbluray-dev build dependency (in universe).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* GIO - GLib Input, Output and Streaming Library
2
 
 * 
3
 
 * Copyright (C) 2006-2007 Red Hat, Inc.
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
 
 * Author: Alexander Larsson <alexl@redhat.com>
21
 
 */
22
 
 
23
 
#include <config.h>
24
 
 
25
 
#include <unistd.h>
26
 
#include <sys/types.h>
27
 
#include <sys/socket.h>
28
 
#include <sys/un.h>
29
 
 
30
 
#include <glib.h>
31
 
#include <dbus/dbus.h>
32
 
#include <glib/gi18n.h>
33
 
#include "gvfsjobunmount.h"
34
 
#include "gvfsdbusutils.h"
35
 
#include "gvfsdaemonprotocol.h"
36
 
 
37
 
G_DEFINE_TYPE (GVfsJobUnmount, g_vfs_job_unmount, G_VFS_TYPE_JOB_DBUS)
38
 
 
39
 
static void     run        (GVfsJob *job);
40
 
static gboolean try        (GVfsJob *job);
41
 
static void     send_reply (GVfsJob *job);
42
 
static DBusMessage *create_reply (GVfsJob *job,
43
 
                                  DBusConnection *connection,
44
 
                                  DBusMessage *message);
45
 
 
46
 
static void
47
 
g_vfs_job_unmount_finalize (GObject *object)
48
 
{
49
 
  GVfsJobUnmount *job;
50
 
 
51
 
   job = G_VFS_JOB_UNMOUNT (object);
52
 
 
53
 
  if (job->mount_source)
54
 
    g_object_unref (job->mount_source);
55
 
 
56
 
  if (G_OBJECT_CLASS (g_vfs_job_unmount_parent_class)->finalize)
57
 
    (*G_OBJECT_CLASS (g_vfs_job_unmount_parent_class)->finalize) (object);
58
 
}
59
 
 
60
 
static void
61
 
g_vfs_job_unmount_class_init (GVfsJobUnmountClass *klass)
62
 
{
63
 
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
64
 
  GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
65
 
  GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
66
 
  
67
 
  gobject_class->finalize = g_vfs_job_unmount_finalize;
68
 
  job_class->run = run;
69
 
  job_class->try = try;
70
 
  job_class->send_reply = send_reply;
71
 
 
72
 
  job_dbus_class->create_reply = create_reply;
73
 
 
74
 
}
75
 
 
76
 
static void
77
 
g_vfs_job_unmount_init (GVfsJobUnmount *job)
78
 
{
79
 
}
80
 
 
81
 
GVfsJob *
82
 
g_vfs_job_unmount_new (DBusConnection *connection,
83
 
                       DBusMessage *message,
84
 
                       GVfsBackend *backend)
85
 
{
86
 
  GVfsJobUnmount *job;
87
 
  DBusMessage *reply;
88
 
  DBusMessageIter iter;
89
 
  DBusError derror;
90
 
  const char *dbus_id, *obj_path;
91
 
  guint32 flags;
92
 
  
93
 
  
94
 
  dbus_error_init (&derror);
95
 
  dbus_message_iter_init (message, &iter);
96
 
 
97
 
  if (!_g_dbus_message_iter_get_args (&iter, &derror, 
98
 
                                      DBUS_TYPE_STRING, &dbus_id,
99
 
                                      DBUS_TYPE_OBJECT_PATH, &obj_path,
100
 
                                      DBUS_TYPE_UINT32, &flags,
101
 
                                      0))
102
 
    {
103
 
      reply = dbus_message_new_error (message,
104
 
                                      derror.name,
105
 
                                      derror.message);
106
 
      dbus_error_free (&derror);
107
 
 
108
 
      dbus_connection_send (connection, reply, NULL);
109
 
      dbus_message_unref (reply);
110
 
      return NULL;
111
 
    }
112
 
 
113
 
  g_debug ("g_vfs_job_unmount_new request: %p\n", message);
114
 
  
115
 
  job = g_object_new (G_VFS_TYPE_JOB_UNMOUNT,
116
 
                      "message", message,
117
 
                      "connection", connection,
118
 
                      NULL);
119
 
 
120
 
  job->backend = backend;
121
 
  job->flags = flags;
122
 
  job->mount_source = g_mount_source_new (dbus_id, obj_path);
123
 
  
124
 
  return G_VFS_JOB (job);
125
 
}
126
 
 
127
 
static void
128
 
run (GVfsJob *job)
129
 
{
130
 
  GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (job);
131
 
  GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
132
 
 
133
 
  class->unmount (op_job->backend,
134
 
                  op_job,
135
 
                  op_job->flags,
136
 
                  op_job->mount_source);
137
 
}
138
 
 
139
 
static gboolean
140
 
job_finish_immediately_if_possible (GVfsJobUnmount *op_job)
141
 
{
142
 
  GVfsBackend      *backend = op_job->backend;
143
 
  GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
144
 
  gboolean is_busy;
145
 
  gboolean force_unmount;
146
 
 
147
 
  if (class->try_unmount != NULL || class->unmount != NULL)
148
 
    return FALSE;
149
 
 
150
 
  is_busy = g_vfs_backend_has_blocking_processes (backend);
151
 
  force_unmount = op_job->flags & G_MOUNT_UNMOUNT_FORCE;
152
 
 
153
 
  if (is_busy && ! force_unmount)
154
 
    g_vfs_job_failed_literal (G_VFS_JOB (op_job),
155
 
                              G_IO_ERROR, G_IO_ERROR_BUSY,
156
 
                              _("Filesystem is busy"));
157
 
  else
158
 
    g_vfs_job_succeeded (G_VFS_JOB (op_job));
159
 
 
160
 
  return TRUE;
161
 
}
162
 
 
163
 
static void
164
 
unmount_cb (GVfsBackend  *backend,
165
 
            GAsyncResult *res,
166
 
            gpointer      user_data)
167
 
{
168
 
  GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (user_data);
169
 
  GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
170
 
  gboolean should_unmount;
171
 
  gboolean finished;
172
 
 
173
 
  should_unmount = g_vfs_backend_unmount_with_operation_finish (backend,
174
 
                                                                res);
175
 
 
176
 
  if (should_unmount)
177
 
    op_job->flags |= G_MOUNT_UNMOUNT_FORCE;
178
 
 
179
 
  finished = job_finish_immediately_if_possible (op_job);
180
 
 
181
 
  if (! finished)
182
 
    {
183
 
      gboolean run_in_thread = TRUE;
184
 
 
185
 
      if (class->try_unmount != NULL)
186
 
        run_in_thread = ! class->try_unmount (op_job->backend,
187
 
                                              op_job,
188
 
                                              op_job->flags,
189
 
                                              op_job->mount_source);
190
 
 
191
 
       if (run_in_thread)
192
 
        g_vfs_daemon_run_job_in_thread (g_vfs_backend_get_daemon (backend),
193
 
                                        G_VFS_JOB (op_job));
194
 
    }
195
 
}
196
 
 
197
 
static gboolean
198
 
try (GVfsJob *job)
199
 
{
200
 
  GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (job);
201
 
  GVfsBackend    *backend = op_job->backend;
202
 
  GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
203
 
  gboolean is_busy;
204
 
  gboolean force_unmount;
205
 
 
206
 
  is_busy = g_vfs_backend_has_blocking_processes (backend);
207
 
  force_unmount = op_job->flags & G_MOUNT_UNMOUNT_FORCE;
208
 
  
209
 
  if (is_busy && ! force_unmount
210
 
      && ! g_mount_source_is_dummy (op_job->mount_source))
211
 
    {
212
 
      g_vfs_backend_unmount_with_operation (backend,
213
 
                                            op_job->mount_source,
214
 
                                            (GAsyncReadyCallback) unmount_cb,
215
 
                                            op_job);
216
 
      return TRUE;
217
 
    }
218
 
 
219
 
  if (job_finish_immediately_if_possible (op_job))
220
 
    return TRUE;
221
 
  else
222
 
    return class->try_unmount (op_job->backend,
223
 
                               op_job,
224
 
                               op_job->flags,
225
 
                               op_job->mount_source);
226
 
}
227
 
 
228
 
static void
229
 
unregister_mount_callback (DBusMessage *unmount_reply,
230
 
                           GError *error,
231
 
                           gpointer user_data)
232
 
{
233
 
  GVfsBackend *backend;
234
 
  GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (user_data);
235
 
 
236
 
  g_debug ("unregister_mount_callback, unmount_reply: %p, error: %p\n", unmount_reply, error);
237
 
 
238
 
  backend = op_job->backend;
239
 
  (*G_VFS_JOB_CLASS (g_vfs_job_unmount_parent_class)->send_reply) (G_VFS_JOB (op_job));
240
 
 
241
 
  /* Unlink job source from daemon */
242
 
  g_vfs_job_source_closed (G_VFS_JOB_SOURCE (backend));
243
 
 
244
 
  g_vfs_daemon_close_active_channels (g_vfs_backend_get_daemon ((backend)));
245
 
}
246
 
 
247
 
/* Might be called on an i/o thread */
248
 
static void
249
 
send_reply (GVfsJob *job)
250
 
{
251
 
  GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (job);
252
 
 
253
 
  g_debug ("send_reply, failed: %d\n", job->failed);
254
 
 
255
 
  if (job->failed)
256
 
    (*G_VFS_JOB_CLASS (g_vfs_job_unmount_parent_class)->send_reply) (G_VFS_JOB (op_job));
257
 
  else
258
 
    {
259
 
      GVfsBackend *backend = op_job->backend;
260
 
 
261
 
      /* Setting the backend to block requests will also
262
 
         set active GVfsChannels to block requets  */
263
 
      g_vfs_backend_set_block_requests (backend);
264
 
      g_vfs_backend_unregister_mount (backend,
265
 
                                      unregister_mount_callback,
266
 
                                      job);
267
 
    }
268
 
}
269
 
 
270
 
/* Might be called on an i/o thread */
271
 
static DBusMessage *
272
 
create_reply (GVfsJob *job,
273
 
              DBusConnection *connection,
274
 
              DBusMessage *message)
275
 
{
276
 
  DBusMessage *reply;
277
 
 
278
 
  reply = dbus_message_new_method_return (message);
279
 
 
280
 
  return reply;
281
 
}