Fixed captive_file_file_info_set() sandbox child interface SIGSEGV.
[captive.git] / src / libcaptive / sandbox / server-File.c
1 /* $Id$
2  * CORBA/ORBit server side of File object, ran by sandbox_child()
3  * Copyright (C) 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 "server-File.h"        /* self */
23 #include "sandbox.h"
24 #include <glib/gmessages.h>
25 #include "captive/macros.h"
26 #include "split.h"
27 #include "FileInfo.h"
28 #include "../client/vfs-slave.h"
29
30
31 static void impl_Captive_File_fini(impl_POA_Captive_File *servant,CORBA_Environment *ev);
32 static void impl_Captive_File_read(impl_POA_Captive_File *servant,Captive_Bytes **buffer,
33                 const Captive_GnomeVFSFileSize num_bytes,CORBA_Environment *ev);
34 static void impl_Captive_File_write(impl_POA_Captive_File *servant,
35                 const Captive_Bytes *buffer,Captive_GnomeVFSFileSize *bytes_written_return,CORBA_Environment *ev);
36 static void impl_Captive_File_seek(impl_POA_Captive_File *servant,
37                 const Captive_GnomeVFSSeekPosition whence,const Captive_GnomeVFSFileOffset offset,CORBA_Environment *ev);
38 static void impl_Captive_File_tell
39                 (impl_POA_Captive_File *servant,Captive_GnomeVFSFileOffset *offset_return,CORBA_Environment *ev);
40 static void impl_Captive_File_remove(impl_POA_Captive_File *servant,CORBA_Environment *ev);
41 static void impl_Captive_File_file_info_get
42                 (impl_POA_Captive_File *servant,Captive_CaptiveFileInfoObject **file_info,CORBA_Environment *ev);
43 static void impl_Captive_File_file_info_set(impl_POA_Captive_File *servant,
44                 const Captive_CaptiveFileInfoObject *file_info,const Captive_GnomeVFSSetFileInfoMask mask,CORBA_Environment *ev);
45 static void impl_Captive_File_truncate
46                 (impl_POA_Captive_File *servant,const Captive_GnomeVFSFileSize file_size,CORBA_Environment *ev);
47 static void impl_Captive_File_move
48                 (impl_POA_Captive_File *servant,const CORBA_char *pathname_new,const CORBA_boolean force_replace,CORBA_Environment *ev);
49 static void impl_Captive_File_shutdown(impl_POA_Captive_File *servant,CORBA_Environment *ev);
50
51
52 static PortableServer_ServantBase__epv impl_Captive_File_base_epv={
53         NULL,   /* _private data */
54         (gpointer)&impl_Captive_File_fini,      /* finalize routine */
55         NULL,   /* default_POA routine */
56         };
57 static POA_Captive_File__epv impl_Captive_File_epv={
58         NULL,   /* _private */
59         (gpointer)&impl_Captive_File_read,
60         (gpointer)&impl_Captive_File_write,
61         (gpointer)&impl_Captive_File_seek,
62         (gpointer)&impl_Captive_File_tell,
63         (gpointer)&impl_Captive_File_remove,
64         (gpointer)&impl_Captive_File_file_info_get,
65         (gpointer)&impl_Captive_File_file_info_set,
66         (gpointer)&impl_Captive_File_truncate,
67         (gpointer)&impl_Captive_File_move,
68         (gpointer)&impl_Captive_File_shutdown,
69         };
70 static POA_Captive_File__vepv impl_Captive_File_vepv={
71         &impl_Captive_File_base_epv,
72         &impl_Captive_File_epv,
73         };
74
75
76 Captive_File impl_Captive_File__create(PortableServer_POA poa,CORBA_Environment *ev)
77 {
78 Captive_File retval;
79 impl_POA_Captive_File *newservant;
80 PortableServer_ObjectId *objid;
81
82         captive_new0(newservant);       /* FIXME: leak */
83         newservant->servant.vepv=&impl_Captive_File_vepv;
84         newservant->poa=poa;
85         newservant->captive_file_object=NULL;
86         POA_Captive_File__init((PortableServer_Servant)newservant,ev);
87         objid=PortableServer_POA_activate_object(poa,newservant,ev);
88         CORBA_free(objid);
89         retval=PortableServer_POA_servant_to_reference(poa,newservant,ev);
90
91         return retval;
92 }
93
94
95 static void impl_Captive_File_fini(impl_POA_Captive_File *servant,CORBA_Environment *ev)
96 {
97         if (servant->captive_file_object) {
98                 g_object_unref(servant->captive_file_object);
99                 servant->captive_file_object=NULL;
100                 }
101 }
102
103
104 static void impl_Captive_File__destroy(impl_POA_Captive_File *servant,CORBA_Environment *ev)
105 {
106 PortableServer_ObjectId *objid;
107
108         objid=PortableServer_POA_servant_to_id(servant->poa,servant,ev);
109         PortableServer_POA_deactivate_object(servant->poa,objid,ev);
110         CORBA_free(objid);
111         impl_Captive_File_fini(servant,ev);
112         g_free(servant);
113 }
114
115
116 Captive_File impl_Captive_Vfs_file_new_open
117                 (impl_POA_Captive_Vfs *servant,const CORBA_char *pathname,const Captive_GnomeVFSOpenMode mode,CORBA_Environment *ev)
118 {
119 Captive_File retval;
120 impl_POA_Captive_File *retval_servant;
121 GnomeVFSResult errvfsresult;
122
123         g_return_val_if_fail(CAPTIVE_VFS_SLAVE_IS_OBJECT(servant->captive_vfs_object),NULL);    /* not yet initialized? */
124
125         retval=impl_Captive_File__create(servant->poa,ev);
126         if (ev->_major!=CORBA_NO_EXCEPTION)
127                 return NULL;
128
129         retval_servant=PortableServer_POA_reference_to_servant(servant->poa,retval,ev);
130         if (ev->_major!=CORBA_NO_EXCEPTION)
131                 return NULL;    /* 'retval' leak */
132
133         if (GNOME_VFS_OK!=(errvfsresult=captive_file_new_open(&retval_servant->captive_file_object,
134                         servant->captive_vfs_object,pathname,mode))) {
135                 impl_Captive_File__destroy(retval_servant,ev);
136                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
137                 return NULL;
138                 }
139
140         return retval;
141 }
142
143
144 Captive_File impl_Captive_Vfs_file_new_create(impl_POA_Captive_Vfs *servant,const CORBA_char *pathname,
145                 const Captive_GnomeVFSOpenMode mode,const CORBA_boolean exclusive,const CORBA_unsigned_long perm,CORBA_Environment *ev)
146 {
147 Captive_File retval;
148 impl_POA_Captive_File *retval_servant;
149 GnomeVFSResult errvfsresult;
150
151         g_return_val_if_fail(CAPTIVE_VFS_SLAVE_IS_OBJECT(servant->captive_vfs_object),NULL);    /* not yet initialized? */
152
153         retval=impl_Captive_File__create(servant->poa,ev);
154         if (ev->_major!=CORBA_NO_EXCEPTION)
155                 return NULL;
156
157         retval_servant=PortableServer_POA_reference_to_servant(servant->poa,retval,ev);
158         if (ev->_major!=CORBA_NO_EXCEPTION)
159                 return NULL;    /* 'retval' leak */
160
161         if (GNOME_VFS_OK!=(errvfsresult=captive_file_new_create(&retval_servant->captive_file_object,
162                         servant->captive_vfs_object,pathname,mode,exclusive,perm))) {
163                 impl_Captive_File__destroy(retval_servant,ev);
164                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
165                 return NULL;
166                 }
167
168         return retval;
169 }
170
171
172 static void impl_Captive_File_read(impl_POA_Captive_File *servant,Captive_Bytes **buffer_corba_return,
173                 const Captive_GnomeVFSFileSize num_bytes,CORBA_Environment *ev)
174 {
175 Captive_Bytes *buffer_corba;
176 GnomeVFSFileSize bytes_read;
177 GnomeVFSResult errvfsresult;
178
179         buffer_corba=Captive_Bytes__alloc();
180         buffer_corba->_maximum=num_bytes;
181         buffer_corba->_length=0;
182         buffer_corba->_buffer=Captive_Bytes_allocbuf(buffer_corba->_maximum);
183         buffer_corba->_release=TRUE;
184
185         if (GNOME_VFS_OK!=(errvfsresult=captive_file_read(servant->captive_file_object,
186                         buffer_corba->_buffer,num_bytes,&bytes_read))) {
187                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
188                 Captive_Bytes__freekids(buffer_corba,NULL/* 'd'; meaning? */);
189                 CORBA_free(buffer_corba);
190                 return;
191                 }
192
193         buffer_corba->_length=bytes_read;
194         *buffer_corba_return=buffer_corba;
195 }
196
197
198 static void impl_Captive_File_write(impl_POA_Captive_File *servant,
199                 const Captive_Bytes *buffer_corba,Captive_GnomeVFSFileSize *bytes_written_return,CORBA_Environment *ev)
200 {
201 GnomeVFSFileSize bytes_written;
202 GnomeVFSResult errvfsresult;
203
204         if (GNOME_VFS_OK!=(errvfsresult=captive_file_write(servant->captive_file_object,
205                         buffer_corba->_buffer,buffer_corba->_length,&bytes_written))) {
206                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
207                 return;
208                 }
209
210         *bytes_written_return=bytes_written;
211 }
212
213
214 static void impl_Captive_File_seek(impl_POA_Captive_File *servant,
215                 const Captive_GnomeVFSSeekPosition whence,const Captive_GnomeVFSFileOffset offset,CORBA_Environment *ev)
216 {
217 GnomeVFSResult errvfsresult;
218
219         if (GNOME_VFS_OK!=(errvfsresult=captive_file_seek(servant->captive_file_object,whence,offset))) {
220                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
221                 return;
222                 }
223 }
224
225
226 static void impl_Captive_File_tell
227                 (impl_POA_Captive_File *servant,Captive_GnomeVFSFileOffset *offset_return,CORBA_Environment *ev)
228 {
229 GnomeVFSFileOffset offset_captive;
230 GnomeVFSResult errvfsresult;
231
232         if (GNOME_VFS_OK!=(errvfsresult=captive_file_tell(servant->captive_file_object,&offset_captive))) {
233                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
234                 return;
235                 }
236         
237         *offset_return=offset_captive;
238 }
239
240
241 static void impl_Captive_File_remove(impl_POA_Captive_File *servant,CORBA_Environment *ev)
242 {
243 GnomeVFSResult errvfsresult;
244
245         if (GNOME_VFS_OK!=(errvfsresult=captive_file_remove(servant->captive_file_object))) {
246                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
247                 return;
248                 }
249 }
250
251
252 static void impl_Captive_File_file_info_get
253                 (impl_POA_Captive_File *servant,Captive_CaptiveFileInfoObject **file_info_corba_return,CORBA_Environment *ev)
254 {
255 CaptiveFileInfoObject *file_info_captive;
256 GnomeVFSResult errvfsresult;
257 Captive_CaptiveFileInfoObject *file_info_corba;
258
259         if (GNOME_VFS_OK!=(errvfsresult=captive_file_file_info_get(servant->captive_file_object,&file_info_captive))) {
260                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
261                 return;
262                 }
263
264         file_info_corba=Captive_CaptiveFileInfoObject__alloc();
265
266         errvfsresult=captive_sandbox_file_info_captive_to_corba(file_info_corba,file_info_captive);
267         g_object_unref(file_info_captive);
268
269         if (GNOME_VFS_OK!=errvfsresult) {
270                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
271                 Captive_CaptiveFileInfoObject__freekids(file_info_corba,NULL/* 'd'; meaning? */);
272                 CORBA_free(file_info_corba);
273                 return;
274                 }
275
276         *file_info_corba_return=file_info_corba;
277 }
278
279
280 static void impl_Captive_File_file_info_set(impl_POA_Captive_File *servant,
281                 const Captive_CaptiveFileInfoObject *file_info_corba,const Captive_GnomeVFSSetFileInfoMask mask,CORBA_Environment *ev)
282 {
283 CaptiveFileInfoObject *file_info_captive;
284 GnomeVFSResult errvfsresult;
285
286         if (GNOME_VFS_OK!=(errvfsresult=captive_file_info_object_new(&file_info_captive))) {
287                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
288                 return;
289                 }
290
291         if (GNOME_VFS_OK!=(errvfsresult=captive_sandbox_file_info_corba_to_captive(
292                         file_info_captive,file_info_corba))) {
293                 g_object_unref(file_info_captive);
294                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
295                 return;
296                 }
297
298         errvfsresult=captive_file_file_info_set(servant->captive_file_object,file_info_captive,mask);
299         g_object_unref(file_info_captive);
300
301         if (GNOME_VFS_OK!=errvfsresult) {
302                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
303                 return;
304                 }
305 }
306
307
308 static void impl_Captive_File_truncate
309                 (impl_POA_Captive_File *servant,const Captive_GnomeVFSFileSize file_size,CORBA_Environment *ev)
310 {
311 GnomeVFSResult errvfsresult;
312
313         if (GNOME_VFS_OK!=(errvfsresult=captive_file_truncate(servant->captive_file_object,file_size))) {
314                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
315                 return;
316                 }
317 }
318
319
320 static void impl_Captive_File_move
321                 (impl_POA_Captive_File *servant,const CORBA_char *pathname_new,const CORBA_boolean force_replace,CORBA_Environment *ev)
322 {
323 GnomeVFSResult errvfsresult;
324
325         if (GNOME_VFS_OK!=(errvfsresult=captive_file_move(servant->captive_file_object,pathname_new,force_replace))) {
326                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
327                 return;
328                 }
329 }
330
331
332 static gboolean impl_Captive_File_shutdown_idle(impl_POA_Captive_File *servant /* data */)
333 {
334         impl_Captive_File__destroy(servant,&captive_corba_ev);
335         g_assert(validate_CORBA_Environment(&captive_corba_ev));
336
337         return FALSE;   /* remove me */
338 }
339
340 static void impl_Captive_File_shutdown(impl_POA_Captive_File *servant,CORBA_Environment *ev)
341 {
342 GSource *source;
343
344         /* Shutdown 'servant->captive_file_object' synchronously as it may
345          * flush its buffers needed to be transferred to our parent.
346          */
347         impl_Captive_File_fini(servant,&captive_corba_ev);
348         g_assert(validate_CORBA_Environment(&captive_corba_ev));
349
350         /* Do not call impl_Captive_File__destroy() directly as we would fail
351          * to finish this CORBA method call properly.
352          * Do not call g_idle_add_full() as it would miss linc main loop.
353          * FIXME: STATUS_SHARING_VIOLATION error during batch processing.
354          *  - probably exclusive access to be changed to shareable one
355          */
356   source=g_idle_source_new ();
357         g_source_set_priority(source,G_PRIORITY_LOW);
358   g_source_set_callback(
359                         source, /* source */
360                         (GSourceFunc)impl_Captive_File_shutdown_idle,   /* func */
361                         servant,        /* data */
362                         NULL);  /* notify */
363   g_source_attach(source,
364                         captive_corba_get_context());   /* context; NULL means 'default context' */
365   g_source_unref(source);
366 }