Implemented vfs_volume_info_get() for proper df(1) entry.
[captive.git] / src / libcaptive / sandbox / server-Vfs.c
1 /* $Id$
2  * CORBA/ORBit server side of Vfs 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-Vfs.h" /* self */
23 #include "sandbox.h"
24 #include <glib/gmessages.h>
25 #include "captive/macros.h"
26 #include "server-Directory.h"
27 #include "server-File.h"
28 #include "split.h"
29 #include "server-GLogFunc.h"
30 #include "client-CaptiveIOChannel.h"
31
32
33 static void impl_Captive_Vfs_fini(impl_POA_Captive_Vfs *servant,CORBA_Environment *ev);
34 static void impl_Captive_Vfs_init
35                 (impl_POA_Captive_Vfs *servant,const Captive_CaptiveOptions *options_corba,CORBA_Environment *ev);
36 static void impl_Captive_Vfs_shutdown(impl_POA_Captive_Vfs *servant,CORBA_Environment *ev);
37 static void impl_Captive_Vfs_volume_info_get
38                 (impl_POA_Captive_Vfs *servant,Captive_CaptiveVfsVolumeInfo *volume_info_corba,CORBA_Environment *ev);
39
40 static PortableServer_ServantBase__epv impl_Captive_Vfs_base_epv={
41         NULL,   /* _private data */
42         (gpointer)&impl_Captive_Vfs_fini,       /* finalize routine */
43         NULL,   /* default_POA routine */
44         };
45 static POA_Captive_Vfs__epv impl_Captive_Vfs_epv={
46         NULL,   /* _private */
47         (gpointer)&impl_Captive_Vfs_init,
48         (gpointer)&impl_Captive_Vfs_shutdown,
49         (gpointer)&impl_Captive_Vfs_directory_new_open,
50         (gpointer)&impl_Captive_Vfs_directory_new_make,
51         (gpointer)&impl_Captive_Vfs_file_new_open,
52         (gpointer)&impl_Captive_Vfs_file_new_create,
53         (gpointer)&impl_Captive_Vfs_volume_info_get,
54         };
55 static POA_Captive_Vfs__vepv impl_Captive_Vfs_vepv={
56         &impl_Captive_Vfs_base_epv,
57         &impl_Captive_Vfs_epv,
58         };
59
60
61 Captive_Vfs impl_Captive_Vfs__create(PortableServer_POA poa,CORBA_Environment *ev)
62 {
63 Captive_Vfs retval;
64 impl_POA_Captive_Vfs *newservant;
65 PortableServer_ObjectId *objid;
66
67         captive_new0(newservant);       /* FIXME: leak */
68         newservant->servant.vepv=&impl_Captive_Vfs_vepv;
69         newservant->poa=poa;
70         newservant->captive_vfs_object=NULL;
71         POA_Captive_Vfs__init((PortableServer_Servant)newservant,ev);
72         objid=PortableServer_POA_activate_object(poa,newservant,ev);
73         CORBA_free(objid);
74         retval=PortableServer_POA_servant_to_reference(poa,newservant,ev);
75
76         return retval;
77 }
78
79
80 static void impl_Captive_Vfs_fini(impl_POA_Captive_Vfs *servant,CORBA_Environment *ev)
81 {
82         if (servant->captive_vfs_object) {
83                 g_object_unref(servant->captive_vfs_object);
84                 servant->captive_vfs_object=NULL;
85                 }
86 }
87
88
89 static Captive_CaptiveIOChannel options_corba_image_iochannel_copy;
90
91 void impl_Captive_Vfs__destroy(impl_POA_Captive_Vfs *servant,CORBA_Environment *ev)
92 {
93 PortableServer_ObjectId *objid;
94
95         objid=PortableServer_POA_servant_to_id(servant->poa,servant,ev);
96         PortableServer_POA_deactivate_object(servant->poa,objid,ev);
97         CORBA_free(objid);
98         impl_Captive_Vfs_fini(servant,ev);
99         CORBA_Object_release(options_corba_image_iochannel_copy,ev);
100         g_free(servant);
101 }
102
103
104 static void options_module_corba_to_options_module_captive
105                 (struct captive_options_module *dest_options_module_captive,const Captive_CaptiveOptionsModule *src_options_module_corba)
106 {
107         g_return_if_fail(dest_options_module_captive!=NULL);
108         g_return_if_fail(src_options_module_corba!=NULL);
109
110         dest_options_module_captive->pathname_utf8=g_strdup(src_options_module_corba->pathname_utf8);
111         dest_options_module_captive->type=CAPTIVE_OPTIONS_MODULE_TYPE_PE32;
112         dest_options_module_captive->u.pe32.base=g_memdup(src_options_module_corba->data._buffer,
113                         src_options_module_corba->data._length);
114         dest_options_module_captive->u.pe32.length=src_options_module_corba->data._length;
115         dest_options_module_captive->u.pe32.mapped=FALSE;
116 }
117
118
119 static void impl_Captive_Vfs_init
120                 (impl_POA_Captive_Vfs *servant,const Captive_CaptiveOptions *options_corba,CORBA_Environment *ev)
121 {
122 struct captive_options options_captive;
123 GnomeVFSResult errvfsresult;
124 guint moduleui;
125
126         g_return_if_fail(servant->captive_vfs_object==NULL);
127
128         options_corba_image_iochannel_copy=CORBA_Object_duplicate(options_corba->image_iochannel,ev);
129         if (ev->_major!=CORBA_NO_EXCEPTION)
130                 return;
131
132         /* impl_Captive_Vfs_init_g_log_func() does its own copy of 'options_corba->g_log_func'. */
133         impl_Captive_Vfs_init_g_log_func(options_corba->g_log_func,options_corba->debug_messages,ev);
134
135         captive_options_init(&options_captive);
136
137         options_module_corba_to_options_module_captive(&options_captive.filesystem,&options_corba->filesystem);
138
139         options_captive.debug_messages=options_corba->debug_messages;
140         options_captive.rwmode        =options_corba->rwmode;
141         options_captive.media         =options_corba->media;
142
143         options_captive.image_iochannel=(GIOChannel *)captive_io_channel_new(
144                         options_corba_image_iochannel_copy,     /* corba_captive_io_channel */
145                         (options_captive.rwmode!=CAPTIVE_OPTION_RWMODE_RO));    /* writeable */
146
147         for (moduleui=0;moduleui<options_corba->load_module._length;moduleui++) {
148 struct captive_options_module *options_module;
149
150                 captive_new(options_module);
151                 options_module_corba_to_options_module_captive(options_module,options_corba->load_module._buffer+moduleui);
152                 options_captive.load_module=g_list_append(options_captive.load_module,options_module);
153                 }
154
155         g_assert(options_captive.sandbox_server_argv==NULL);
156
157         if (GNOME_VFS_OK!=(errvfsresult=captive_vfs_new(&servant->captive_vfs_object,&options_captive))) {
158                 CORBA_exception_set(ev,CORBA_USER_EXCEPTION,ex_Captive_GnomeVFSResultException,GINT_TO_POINTER((gint)errvfsresult));
159                 captive_options_free(&options_captive);
160                 return;
161                 }
162
163         captive_options_free(&options_captive);
164
165         g_assert(servant->captive_vfs_object!=NULL);
166 }
167
168
169 #if 0   /* Currently unused - see impl_Captive_Vfs_shutdown() */
170 static gboolean impl_Captive_Vfs_shutdown_idle(gpointer data /* unused */)
171 {
172         sandbox_child_shutdown();
173
174         return FALSE;   /* remove me */
175 }
176 #endif
177
178 static void impl_Captive_Vfs_shutdown(impl_POA_Captive_Vfs *servant,CORBA_Environment *ev)
179 {
180 #if 0   /* Currently unused - see impl_Captive_Vfs_shutdown() */
181 GSource *source;
182 #endif
183
184         /* Shutdown 'servant->captive_vfs_object' synchronously as it may
185          * flush its buffers needed to be transferred to our parent.
186          */
187         impl_Captive_Vfs_fini(servant,&captive_corba_ev);
188         g_assert(validate_CORBA_Environment(&captive_corba_ev));
189
190         /* Currently we do not do any sandbox child shutdown here as it sometimes
191          * crashes the parent with COMM_FAILURE without proper finish of this
192          * shutdown() CORBA method call. Parent will kill(2) us soon
193          * from its parent-Vfs.c:captive_sandbox_parent_vfs_close() anyway.
194          */
195 #if 0
196         sandbox_child_prepare_shutdown();
197
198         /* Do not call sandbox_child_shutdown() directly as we would fail
199          * to finish this CORBA method call properly.
200          * Do not call g_idle_add_full() as it would miss linc main loop.
201          */
202   source=g_idle_source_new ();
203         g_source_set_priority(source,G_PRIORITY_LOW);
204   g_source_set_callback(
205                         source, /* source */
206                         (GSourceFunc)impl_Captive_Vfs_shutdown_idle,    /* func */
207                         servant,        /* data */
208                         NULL);  /* notify */
209   g_source_attach(source,
210                         g_main_loop_get_context(linc_main_get_loop())); /* context; NULL means 'default context' */
211   g_source_unref(source);
212 #endif
213 }
214
215
216 static void impl_Captive_Vfs_volume_info_get
217                 (impl_POA_Captive_Vfs *servant,Captive_CaptiveVfsVolumeInfo *volume_info_corba,CORBA_Environment *ev)
218 {
219 CaptiveVfsVolumeInfo volume_info_captive;
220 GnomeVFSResult errvfsresult;
221
222         if (GNOME_VFS_OK!=(errvfsresult=captive_vfs_volume_info_get(servant->captive_vfs_object,&volume_info_captive))) {
223                 captive_sandbox_child_GnomeVFSResultException_throw(ev,errvfsresult);
224                 return;
225                 }
226
227         volume_info_corba->block_size     =volume_info_captive.block_size;
228         volume_info_corba->bytes          =volume_info_captive.bytes;
229         volume_info_corba->bytes_free     =volume_info_captive.bytes_free;
230         volume_info_corba->bytes_available=volume_info_captive.bytes_available;
231 }