Initial original import from: fuse-2.4.2-2.fc4
[captive.git] / src / libcaptive / client / vfs-parent.c
1 /* $Id$
2  * captive vfs 'vfs' interface to reactos of sandbox parent
3  * Copyright (C) 2002-2003 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include "vfs-parent.h" /* self */
23 #include <glib/gmessages.h>
24 #include "captive/macros.h"
25 #include "../sandbox/parent-Vfs.h"
26 #include "directory-parent.h"
27 #include "file-parent.h"
28 #include "marshallers.h"
29
30
31 static gpointer captive_vfs_parent_object_parent_class=NULL;
32
33
34 static GnomeVFSResult captive_vfs_parent_init(CaptiveVfsObject *captive_vfs_object);
35 static void captive_vfs_parent_object_dispose(CaptiveVfsParentObject *captive_vfs_parent_object);
36 static void captive_vfs_parent_object_handler_detach(CaptiveVfsParentObject *captive_vfs_parent_object);
37 static void captive_vfs_parent_object_handler_cease(CaptiveVfsParentObject *captive_vfs_parent_object);
38 static void captive_vfs_parent_object_handler_abort(CaptiveVfsParentObject *captive_vfs_parent_object);
39 static GnomeVFSResult captive_vfs_parent_close(CaptiveVfsObject *captive_vfs_object);
40 static GnomeVFSResult captive_vfs_parent_commit(CaptiveVfsObject *captive_vfs_object);
41 static GnomeVFSResult captive_vfs_parent_volume_info_get
42                 (CaptiveVfsObject *captive_vfs_object,CaptiveVfsVolumeInfo *volume_info);
43 static GnomeVFSResult captive_vfs_parent_object_connect_silent(CaptiveVfsParentObject *captive_vfs_parent_object);
44
45
46 /* We need to close the filesystem during custom 'dispose'
47  * as the default GObject g_object_real_dispose() destroys all the signals
48  * first and we would not notify our Connectors during captive_vfs_parent_object_finalize().
49  */
50 static void captive_vfs_parent_object_dispose(CaptiveVfsParentObject *captive_vfs_parent_object)
51 {
52         g_return_if_fail(captive_vfs_parent_object!=NULL);
53
54         captive_vfs_parent_close(CAPTIVE_VFS_OBJECT(captive_vfs_parent_object));        /* errors ignored */
55
56         G_OBJECT_CLASS(captive_vfs_parent_object_parent_class)->dispose((GObject *)captive_vfs_parent_object);
57 }
58
59
60 static void captive_vfs_parent_object_finalize(CaptiveVfsParentObject *captive_vfs_parent_object)
61 {
62         g_return_if_fail(captive_vfs_parent_object!=NULL);
63
64         G_OBJECT_CLASS(captive_vfs_parent_object_parent_class)->finalize((GObject *)captive_vfs_parent_object);
65 }
66
67
68 static void captive_vfs_parent_object_class_init(CaptiveVfsParentObjectClass *class)
69 {
70 GObjectClass *gobject_class=G_OBJECT_CLASS(class);
71 CaptiveVfsObjectClass *captive_vfs_object_class=CAPTIVE_VFS_OBJECT_CLASS(class);
72
73         captive_vfs_parent_object_parent_class=g_type_class_ref(g_type_parent(G_TYPE_FROM_CLASS(class)));
74         gobject_class->dispose=(void (*)(GObject *object))captive_vfs_parent_object_dispose;
75         gobject_class->finalize=(void (*)(GObject *object))captive_vfs_parent_object_finalize;
76
77         captive_vfs_object_class->init=captive_vfs_parent_init;
78         captive_vfs_object_class->commit=captive_vfs_parent_commit;
79         captive_vfs_object_class->volume_info_get=captive_vfs_parent_volume_info_get;
80
81         captive_vfs_object_class->directory_new_open=captive_directory_parent_new_open;
82         captive_vfs_object_class->directory_new_make=captive_directory_parent_new_make;
83
84         captive_vfs_object_class->file_new_open=captive_file_parent_new_open;
85         captive_vfs_object_class->file_new_create=captive_file_parent_new_create;
86
87         class->detach=captive_vfs_parent_object_handler_detach;
88         g_signal_new(
89                         "detach",       /* signal_name */
90                         G_TYPE_FROM_CLASS(class),       /* itype */
91                         G_SIGNAL_RUN_LAST,      /* signal_flags */
92                         G_STRUCT_OFFSET(CaptiveVfsParentObjectClass,detach),    /* class_offset */
93                         NULL,NULL,      /* accumulator,accu_data */
94                         captive_client_VOID__VOID,      /* c_marshaller */
95                         G_TYPE_NONE,0); /* return_type,n_params */
96         class->cease=captive_vfs_parent_object_handler_cease;
97         g_signal_new(
98                         "cease",        /* signal_name */
99                         G_TYPE_FROM_CLASS(class),       /* itype */
100                         G_SIGNAL_RUN_LAST,      /* signal_flags */
101                         G_STRUCT_OFFSET(CaptiveVfsParentObjectClass,cease),     /* class_offset */
102                         NULL,NULL,      /* accumulator,accu_data */
103                         captive_client_VOID__VOID,      /* c_marshaller */
104                         G_TYPE_NONE,0); /* return_type,n_params */
105         class->abort=captive_vfs_parent_object_handler_abort;
106         g_signal_new(
107                         "abort",        /* signal_name */
108                         G_TYPE_FROM_CLASS(class),       /* itype */
109                         G_SIGNAL_RUN_LAST,      /* signal_flags */
110                         G_STRUCT_OFFSET(CaptiveVfsParentObjectClass,abort),     /* class_offset */
111                         NULL,NULL,      /* accumulator,accu_data */
112                         captive_client_VOID__VOID,      /* c_marshaller */
113                         G_TYPE_NONE,0); /* return_type,n_params */
114 }
115
116
117 static void captive_vfs_parent_object_init(CaptiveVfsParentObject *captive_vfs_parent_object)
118 {
119         captive_vfs_parent_object->corba_parent_giochanel_blind=NULL;
120 }
121
122         
123 static void captive_vfs_parent_object_handler_detach(CaptiveVfsParentObject *captive_vfs_parent_object)
124 {
125         g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
126 }
127
128 static void captive_vfs_parent_object_handler_cease(CaptiveVfsParentObject *captive_vfs_parent_object)
129 {
130         g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
131 }
132
133 static void captive_vfs_parent_object_handler_abort(CaptiveVfsParentObject *captive_vfs_parent_object)
134 {
135         g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
136 }
137
138
139 GType captive_vfs_parent_object_get_type(void)
140 {
141 static GType captive_vfs_parent_object_type=0;
142
143         if (!captive_vfs_parent_object_type) {
144 static const GTypeInfo captive_vfs_parent_object_info={
145                                 sizeof(CaptiveVfsParentObjectClass),
146                                 NULL,   /* base_init */
147                                 NULL,   /* base_finalize */
148                                 (GClassInitFunc)captive_vfs_parent_object_class_init,
149                                 NULL,   /* class_finalize */
150                                 NULL,   /* class_data */
151                                 sizeof(CaptiveVfsParentObject),
152                                 5,      /* n_preallocs */
153                                 (GInstanceInitFunc)captive_vfs_parent_object_init,
154                                 };
155
156                 captive_vfs_parent_object_type=g_type_register_static(CAPTIVE_VFS_TYPE_OBJECT,
157                                 "CaptiveVfsParentObject",&captive_vfs_parent_object_info,0);
158                 }
159
160         return captive_vfs_parent_object_type;
161 }
162
163
164 static GnomeVFSResult captive_vfs_parent_init(CaptiveVfsObject *captive_vfs_object)
165 {
166 CaptiveVfsParentObject *captive_vfs_parent_object;
167
168         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
169
170         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(captive_vfs_object);
171
172         return captive_sandbox_parent_vfs_new(captive_vfs_parent_object);
173 }
174
175
176 static GnomeVFSResult captive_vfs_parent_close(CaptiveVfsObject *captive_vfs_object)
177 {
178 CaptiveVfsParentObject *captive_vfs_parent_object;
179 GnomeVFSResult r;
180
181         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
182
183         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(captive_vfs_object);
184
185         if (captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL) {
186                 r=captive_vfs_parent_object_disconnect(captive_vfs_parent_object);
187                 g_assert(captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL);
188                 }
189         else
190                 r=GNOME_VFS_OK;
191
192         if (captive_vfs_parent_object->corba_parent_giochanel_blind_source) {
193                 g_io_channel_unref(captive_vfs_parent_object->corba_parent_giochanel_blind_source);
194                 captive_vfs_parent_object->corba_parent_giochanel_blind_source=NULL;
195                 }
196
197         return r;
198 }
199
200
201 static GnomeVFSResult captive_vfs_parent_commit(CaptiveVfsObject *captive_vfs_object)
202 {
203 CaptiveVfsParentObject *captive_vfs_parent_object;
204 GnomeVFSResult r;
205 gint retried=0;
206
207         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
208
209         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(captive_vfs_object);
210
211         do {
212                 if (captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL
213                                 && GNOME_VFS_OK!=(r=captive_vfs_parent_object_connect_silent(captive_vfs_parent_object)))
214                         return r;
215                 if (GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE
216                                 !=(r=captive_sandbox_parent_vfs_commit(captive_vfs_parent_object)))
217                         return r;
218                 } while (!retried++);
219         return r;
220 }
221
222
223 static GnomeVFSResult captive_vfs_parent_volume_info_get
224                 (CaptiveVfsObject *captive_vfs_object,CaptiveVfsVolumeInfo *volume_info)
225 {
226 CaptiveVfsParentObject *captive_vfs_parent_object;
227 GnomeVFSResult r;
228 gint retried=0;
229
230         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
231         g_return_val_if_fail(volume_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
232
233         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(captive_vfs_object);
234
235         do {
236                 if (captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL
237                                 && GNOME_VFS_OK!=(r=captive_vfs_parent_object_connect(captive_vfs_parent_object)))
238                         return r;
239                 if (GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE
240                                 !=(r=captive_sandbox_parent_vfs_volume_info_get(captive_vfs_parent_object,volume_info)))
241                         return r;
242                 } while (!retried++);
243         return r;
244 }
245
246
247 GnomeVFSResult captive_vfs_parent_object_connect(CaptiveVfsParentObject *captive_vfs_parent_object)
248 {
249         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
250
251         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
252
253         return captive_sandbox_parent_vfs_new(captive_vfs_parent_object);
254 }
255
256
257 static GnomeVFSResult captive_vfs_parent_object_connect_silent(CaptiveVfsParentObject *captive_vfs_parent_object)
258 {
259         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
260
261         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
262
263         return captive_sandbox_parent_vfs_new_silent(captive_vfs_parent_object);
264 }
265
266
267 GnomeVFSResult captive_vfs_parent_object_disconnect(CaptiveVfsParentObject *captive_vfs_parent_object)
268 {
269 GnomeVFSResult r;
270
271         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
272
273         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
274
275         /* Detach all connectors: */
276         g_signal_emit_by_name(captive_vfs_parent_object,"detach");
277
278         /* Some connector detaching broke the connection? */
279         if (captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL) {
280                 /* "abort" should have been emitted by captive_vfs_parent_object_aborted() */
281                 return GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE;
282                 }
283
284         if (GNOME_VFS_OK!=(r=captive_sandbox_parent_vfs_close(captive_vfs_parent_object))) {
285                 /* Some non-ORBit shutdown error may have occured: */
286                 g_signal_emit_by_name(captive_vfs_parent_object,"abort");
287                 return r;
288                 }
289
290         /* success: */
291         g_signal_emit_by_name(captive_vfs_parent_object,"cease");
292
293         return GNOME_VFS_OK;
294 }
295
296
297 GnomeVFSResult captive_vfs_parent_object_aborted(CaptiveVfsParentObject *captive_vfs_parent_object)
298 {
299 static gint inside=0;
300 GnomeVFSResult r;
301
302         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
303
304         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
305
306         /* Prevent looping by COMM_FAILURE of 'unmount' operation
307          * by captive_sandbox_parent_vfs_close().
308          */
309         g_assert(inside>=0);
310         if (inside)
311                 return GNOME_VFS_OK;
312         inside++;
313
314         g_signal_emit_by_name(captive_vfs_parent_object,"abort");
315
316         r=captive_sandbox_parent_vfs_close(captive_vfs_parent_object);
317
318         g_assert(inside==1);
319         inside--;
320
321         return r;
322 }