Report all dirty objects corrupted by each sandbox crash.
[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
44
45 /* We need to close the filesystem during custom 'dispose'
46  * as the default GObject g_object_real_dispose() destroys all the signals
47  * first and we would not notify our Connectors during captive_vfs_parent_object_finalize().
48  */
49 static void captive_vfs_parent_object_dispose(CaptiveVfsParentObject *captive_vfs_parent_object)
50 {
51         g_return_if_fail(captive_vfs_parent_object!=NULL);
52
53         captive_vfs_parent_close(CAPTIVE_VFS_OBJECT(captive_vfs_parent_object));        /* errors ignored */
54
55         G_OBJECT_CLASS(captive_vfs_parent_object_parent_class)->dispose((GObject *)captive_vfs_parent_object);
56 }
57
58
59 static void captive_vfs_parent_object_finalize(CaptiveVfsParentObject *captive_vfs_parent_object)
60 {
61         g_return_if_fail(captive_vfs_parent_object!=NULL);
62
63         G_OBJECT_CLASS(captive_vfs_parent_object_parent_class)->finalize((GObject *)captive_vfs_parent_object);
64 }
65
66
67 static void captive_vfs_parent_object_class_init(CaptiveVfsParentObjectClass *class)
68 {
69 GObjectClass *gobject_class=G_OBJECT_CLASS(class);
70 CaptiveVfsObjectClass *captive_vfs_object_class=CAPTIVE_VFS_OBJECT_CLASS(class);
71
72         captive_vfs_parent_object_parent_class=g_type_class_ref(g_type_parent(G_TYPE_FROM_CLASS(class)));
73         gobject_class->dispose=(void (*)(GObject *object))captive_vfs_parent_object_dispose;
74         gobject_class->finalize=(void (*)(GObject *object))captive_vfs_parent_object_finalize;
75
76         captive_vfs_object_class->init=captive_vfs_parent_init;
77         captive_vfs_object_class->commit=captive_vfs_parent_commit;
78         captive_vfs_object_class->volume_info_get=captive_vfs_parent_volume_info_get;
79
80         captive_vfs_object_class->directory_new_open=captive_directory_parent_new_open;
81         captive_vfs_object_class->directory_new_make=captive_directory_parent_new_make;
82
83         captive_vfs_object_class->file_new_open=captive_file_parent_new_open;
84         captive_vfs_object_class->file_new_create=captive_file_parent_new_create;
85
86         class->detach=captive_vfs_parent_object_handler_detach;
87         g_signal_new(
88                         "detach",       /* signal_name */
89                         G_TYPE_FROM_CLASS(class),       /* itype */
90                         G_SIGNAL_RUN_LAST,      /* signal_flags */
91                         G_STRUCT_OFFSET(CaptiveVfsParentObjectClass,detach),    /* class_offset */
92                         NULL,NULL,      /* accumulator,accu_data */
93                         captive_client_VOID__VOID,      /* c_marshaller */
94                         G_TYPE_NONE,0); /* return_type,n_params */
95         class->cease=captive_vfs_parent_object_handler_cease;
96         g_signal_new(
97                         "cease",        /* signal_name */
98                         G_TYPE_FROM_CLASS(class),       /* itype */
99                         G_SIGNAL_RUN_LAST,      /* signal_flags */
100                         G_STRUCT_OFFSET(CaptiveVfsParentObjectClass,cease),     /* class_offset */
101                         NULL,NULL,      /* accumulator,accu_data */
102                         captive_client_VOID__VOID,      /* c_marshaller */
103                         G_TYPE_NONE,0); /* return_type,n_params */
104         class->abort=captive_vfs_parent_object_handler_abort;
105         g_signal_new(
106                         "abort",        /* signal_name */
107                         G_TYPE_FROM_CLASS(class),       /* itype */
108                         G_SIGNAL_RUN_LAST,      /* signal_flags */
109                         G_STRUCT_OFFSET(CaptiveVfsParentObjectClass,abort),     /* class_offset */
110                         NULL,NULL,      /* accumulator,accu_data */
111                         captive_client_VOID__VOID,      /* c_marshaller */
112                         G_TYPE_NONE,0); /* return_type,n_params */
113 }
114
115
116 static void captive_vfs_parent_object_init(CaptiveVfsParentObject *captive_vfs_parent_object)
117 {
118         captive_vfs_parent_object->corba_parent_giochanel_blind=NULL;
119 }
120
121         
122 static void captive_vfs_parent_object_handler_detach(CaptiveVfsParentObject *captive_vfs_parent_object)
123 {
124         g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
125 }
126
127 static void captive_vfs_parent_object_handler_cease(CaptiveVfsParentObject *captive_vfs_parent_object)
128 {
129         g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
130 }
131
132 static void captive_vfs_parent_object_handler_abort(CaptiveVfsParentObject *captive_vfs_parent_object)
133 {
134         g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
135 }
136
137
138 GType captive_vfs_parent_object_get_type(void)
139 {
140 static GType captive_vfs_parent_object_type=0;
141
142         if (!captive_vfs_parent_object_type) {
143 static const GTypeInfo captive_vfs_parent_object_info={
144                                 sizeof(CaptiveVfsParentObjectClass),
145                                 NULL,   /* base_init */
146                                 NULL,   /* base_finalize */
147                                 (GClassInitFunc)captive_vfs_parent_object_class_init,
148                                 NULL,   /* class_finalize */
149                                 NULL,   /* class_data */
150                                 sizeof(CaptiveVfsParentObject),
151                                 5,      /* n_preallocs */
152                                 (GInstanceInitFunc)captive_vfs_parent_object_init,
153                                 };
154
155                 captive_vfs_parent_object_type=g_type_register_static(CAPTIVE_VFS_TYPE_OBJECT,
156                                 "CaptiveVfsParentObject",&captive_vfs_parent_object_info,0);
157                 }
158
159         return captive_vfs_parent_object_type;
160 }
161
162
163 static GnomeVFSResult captive_vfs_parent_init(CaptiveVfsObject *captive_vfs_object)
164 {
165 CaptiveVfsParentObject *captive_vfs_parent_object;
166
167         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
168
169         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(captive_vfs_object);
170
171         return captive_sandbox_parent_vfs_new(captive_vfs_parent_object);
172 }
173
174
175 static GnomeVFSResult captive_vfs_parent_close(CaptiveVfsObject *captive_vfs_object)
176 {
177 CaptiveVfsParentObject *captive_vfs_parent_object;
178 GnomeVFSResult r;
179
180         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
181
182         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(captive_vfs_object);
183
184         if (captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL) {
185                 r=captive_vfs_parent_object_disconnect(captive_vfs_parent_object);
186                 g_assert(captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL);
187                 }
188         else
189                 r=GNOME_VFS_OK;
190
191         return r;
192 }
193
194
195 static GnomeVFSResult captive_vfs_parent_commit(CaptiveVfsObject *captive_vfs_object)
196 {
197 CaptiveVfsParentObject *captive_vfs_parent_object;
198 GnomeVFSResult r;
199 gint retried=0;
200
201         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
202
203         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(captive_vfs_object);
204
205         do {
206                 if (captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL
207                                 && GNOME_VFS_OK!=(r=captive_vfs_parent_object_connect(captive_vfs_parent_object)))
208                         return r;
209                 if (GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE
210                                 !=(r=captive_sandbox_parent_vfs_commit(captive_vfs_parent_object)))
211                         return r;
212                 } while (!retried++);
213         return r;
214 }
215
216
217 static GnomeVFSResult captive_vfs_parent_volume_info_get
218                 (CaptiveVfsObject *captive_vfs_object,CaptiveVfsVolumeInfo *volume_info)
219 {
220 CaptiveVfsParentObject *captive_vfs_parent_object;
221 GnomeVFSResult r;
222 gint retried=0;
223
224         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
225         g_return_val_if_fail(volume_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
226
227         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(captive_vfs_object);
228
229         do {
230                 if (captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL
231                                 && GNOME_VFS_OK!=(r=captive_vfs_parent_object_connect(captive_vfs_parent_object)))
232                         return r;
233                 if (GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE
234                                 !=(r=captive_sandbox_parent_vfs_volume_info_get(captive_vfs_parent_object,volume_info)))
235                         return r;
236                 } while (!retried++);
237         return r;
238 }
239
240
241 GnomeVFSResult captive_vfs_parent_object_connect(CaptiveVfsParentObject *captive_vfs_parent_object)
242 {
243         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
244
245         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
246
247         return captive_sandbox_parent_vfs_new(captive_vfs_parent_object);
248 }
249
250
251 GnomeVFSResult captive_vfs_parent_object_disconnect(CaptiveVfsParentObject *captive_vfs_parent_object)
252 {
253 GnomeVFSResult r;
254
255         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
256
257         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
258
259         /* Detach all connectors: */
260         g_signal_emit_by_name(captive_vfs_parent_object,"detach");
261
262         /* Some connector detaching broke the connection? */
263         if (captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL) {
264                 /* "abort" should have been emitted by captive_vfs_parent_object_aborted() */
265                 return GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE;
266                 }
267
268         if (GNOME_VFS_OK!=(r=captive_sandbox_parent_vfs_close(captive_vfs_parent_object))) {
269                 /* Some non-ORBit shutdown error may have occured: */
270                 g_signal_emit_by_name(captive_vfs_parent_object,"abort");
271                 return r;
272                 }
273
274         /* success: */
275         g_signal_emit_by_name(captive_vfs_parent_object,"cease");
276
277         return GNOME_VFS_OK;
278 }
279
280
281 GnomeVFSResult captive_vfs_parent_object_aborted(CaptiveVfsParentObject *captive_vfs_parent_object)
282 {
283 static gint inside=0;
284 GnomeVFSResult r;
285
286         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
287
288         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
289
290         /* Prevent looping by COMM_FAILURE of 'unmount' operation
291          * by captive_sandbox_parent_vfs_close().
292          */
293         g_assert(inside>=0);
294         if (inside)
295                 return GNOME_VFS_OK;
296         inside++;
297
298         g_signal_emit_by_name(captive_vfs_parent_object,"abort");
299
300         r=captive_sandbox_parent_vfs_close(captive_vfs_parent_object);
301
302         g_assert(inside==1);
303         inside--;
304
305         return r;
306 }