Initial original import from: fuse-2.4.2-2.fc4
[captive.git] / src / libcaptive / sandbox / parent-Vfs.c
1 /* $Id$
2  * CORBA/ORBit client side of Vfs object of sandbox_parent()
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 "parent-Vfs.h" /* self */
23 #include <glib/gmessages.h>
24 #include "split.h"
25 #include "../client/vfs.h"
26 #include "sandbox.h"
27 #include <unistd.h>
28 #include "server-GLogFunc.h"
29 #include "server-CaptiveIOChannel.h"
30 #include <signal.h>     /* for kill(2) */
31 #include <wait.h>
32 #include "../client/giochannel-blind.h" /* for captive_giochannel_blind_commit() */
33 #include <time.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include "captive/macros.h"
37
38
39 GnomeVFSResult captive_sandbox_parent_vfs_new_silent(CaptiveVfsParentObject *captive_vfs_parent_object)
40 {
41 gboolean errbool;
42
43         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
44
45         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
46
47         errbool=captive_sandbox_spawn(captive_vfs_parent_object);
48         g_return_val_if_fail(errbool==TRUE,GNOME_VFS_ERROR_GENERIC);
49
50         return GNOME_VFS_OK;
51 }
52
53
54 GnomeVFSResult captive_sandbox_parent_vfs_new(CaptiveVfsParentObject *captive_vfs_parent_object)
55 {
56 GnomeVFSResult r;
57
58         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
59
60         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
61
62         r=captive_sandbox_parent_vfs_new_silent(captive_vfs_parent_object);
63
64         if (captive_vfs_parent_object->corba_bug_action) {
65 xmlNode *xml_action;
66
67                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "vfs_new",NULL);
68                 xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_vfs_parent_object));
69                 }
70
71         return r;
72 }
73
74
75 static void bug_doc_generate(CaptiveVfsParentObject *captive_vfs_parent_object)
76 {
77 size_t out_fname_size;
78 time_t time_t_local;
79 gchar out_fname[PATH_MAX];
80 int errint;
81 xmlNode *xml_media;
82 const gchar *xml_media_type="???";      /* Prevent: ... might be used uninitialized in this function */
83
84         g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
85
86         xml_media=captive_giochannel_blind_readreport_to_xml(captive_vfs_parent_object->corba_bug,captive_vfs_parent_object->corba_parent_giochanel_blind);
87         switch (CAPTIVE_VFS_OBJECT(captive_vfs_parent_object)->options.media) {
88                 case CAPTIVE_OPTION_MEDIA_CDROM: xml_media_type="cdrom"; break;
89                 case CAPTIVE_OPTION_MEDIA_DISK:  xml_media_type="disk";  break;
90                 default: g_assert_not_reached();
91                 }
92         xmlNewProp(xml_media,BAD_CAST "type",BAD_CAST xml_media_type);
93
94         xmlSetDocCompressMode(captive_vfs_parent_object->corba_bug_doc,9);
95
96         time(&time_t_local);
97         if (!(out_fname_size=strftime(out_fname,sizeof(out_fname),
98                         CAPTIVE_VFS_OBJECT(captive_vfs_parent_object)->options.bug_pathname,localtime(&time_t_local)))) {
99                 g_assert_not_reached();
100                 return;
101                 }
102
103         /* xmlSaveFormatFileEnc() would be better to prevent rewriting
104          * of target 'out_fname' but it does not support compression.
105          */
106         errint=xmlSaveFormatFileEnc(out_fname,captive_vfs_parent_object->corba_bug_doc,"UTF-8",
107                         1);     /* format; ==output indenting; FIXME: Is it really indented? */
108         g_assert(errint!=-1);
109 }
110
111
112 static GnomeVFSResult captive_sandbox_parent_vfs_close_silent(CaptiveVfsParentObject *captive_vfs_parent_object)
113 {
114 GnomeVFSResult r;
115 int errint;
116 impl_POA_Captive_GLogFunc *GLogFunc_servant;
117 impl_POA_Captive_CaptiveIOChannel *CaptiveIOChannel_servant;
118 GIOStatus erriostatus;
119
120         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
121
122         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
123
124         Captive_Vfs_shutdown(captive_vfs_parent_object->corba_Vfs_object,&captive_corba_ev);
125         r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object);
126
127         /* We may get called by recursion from captive_sandbox_parent_return_from_CORBA_Environment(): */
128         if (captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL)
129                 return r;
130
131         /* Always clear 'corba_Vfs_object' even if 'r' means failure. */
132         CORBA_Object_release(captive_vfs_parent_object->corba_Vfs_object,&captive_corba_ev);
133         g_assert(validate_CORBA_Environment(&captive_corba_ev));
134         captive_vfs_parent_object->corba_Vfs_object=CORBA_OBJECT_NIL;
135
136         /* Shutdown 'GLogFunc' servant. */
137         GLogFunc_servant=PortableServer_POA_reference_to_servant(captive_corba_poa,
138                         captive_vfs_parent_object->corba_GLogFunc_object,&captive_corba_ev);
139         g_assert(validate_CORBA_Environment(&captive_corba_ev));
140         CORBA_Object_release(captive_vfs_parent_object->corba_GLogFunc_object,&captive_corba_ev);
141         g_assert(validate_CORBA_Environment(&captive_corba_ev));
142         impl_Captive_GLogFunc__destroy(GLogFunc_servant,&captive_corba_ev);
143         g_assert(validate_CORBA_Environment(&captive_corba_ev));
144
145         /* Shutdown 'CaptiveIOChannel' servant. */
146         CaptiveIOChannel_servant=PortableServer_POA_reference_to_servant(captive_corba_poa,
147                         captive_vfs_parent_object->corba_CaptiveIOChannel_object,&captive_corba_ev);
148         g_assert(validate_CORBA_Environment(&captive_corba_ev));
149         CORBA_Object_release(captive_vfs_parent_object->corba_CaptiveIOChannel_object,&captive_corba_ev);
150         g_assert(validate_CORBA_Environment(&captive_corba_ev));
151         impl_Captive_CaptiveIOChannel__destroy(CaptiveIOChannel_servant,&captive_corba_ev);
152         g_assert(validate_CORBA_Environment(&captive_corba_ev));
153
154         /* Close parentheart_fd_write. */
155         if (captive_vfs_parent_object->corba_parentheart_fds_1!=-1) {
156                 errint=close(captive_vfs_parent_object->corba_parentheart_fds_1);
157                 g_return_val_if_fail(errint==0,FALSE);
158                 }
159
160         /* Cleanup linked child socket to our parent '/tmp'. */
161         if (captive_vfs_parent_object->corba_chrooted_orbit_dir) {
162                 if (captive_vfs_parent_object->corba_socketname) {
163 const gchar *socketpathname;
164
165                         socketpathname=captive_printf_alloca("%s/%s",
166                                         captive_vfs_parent_object->corba_chrooted_orbit_dir,captive_vfs_parent_object->corba_socketname);
167                         unlink(socketpathname); /* errors ignored */
168                         g_free(captive_vfs_parent_object->corba_socketname);
169                         captive_vfs_parent_object->corba_socketname=NULL;
170                         }
171                 rmdir(captive_vfs_parent_object->corba_chrooted_orbit_dir);     /* errors ignored */
172                 g_free(captive_vfs_parent_object->corba_chrooted_orbit_dir);
173                 captive_vfs_parent_object->corba_chrooted_orbit_dir=NULL;
174                 }
175
176         /* Cleanup the child process. */
177         if (captive_vfs_parent_object->corba_child_pid!=(pid_t)-1) {
178                 kill(captive_vfs_parent_object->corba_child_pid,SIGKILL);       /* errors ignored */
179                 /* waitpid(2) errors are ignored as we should be immune against failures as the parent. */
180                 waitpid(captive_vfs_parent_object->corba_child_pid,
181                                 NULL,   /* status */
182                                 /* options: !WNOHANG as the child will not be ready yet for waitpid()
183                                  * right after its SIGKILL. As we did SIGKILL I hope it has no chance
184                                  * to block us.
185                                  */
186                                 0);     /* options */
187                 }
188
189         if (r==GNOME_VFS_OK) {
190                 erriostatus=captive_giochannel_blind_commit(captive_vfs_parent_object->corba_parent_giochanel_blind);
191                 g_assert(erriostatus==G_IO_STATUS_NORMAL);
192                 }
193         else {  /* sandbox child failure */
194                 /* Flush the channel to catch all the disk accesses to the bugreport. */
195                 erriostatus=g_io_channel_flush(
196                                 captive_vfs_parent_object->corba_parent_giochanel_blind,        /* channel */
197                                 NULL);  /* error */
198                 g_assert(erriostatus==G_IO_STATUS_NORMAL);
199
200                 /* Summarize the bugreport. */
201                 if (captive_vfs_parent_object->corba_bug_doc)
202                         bug_doc_generate(captive_vfs_parent_object);
203                 }
204         g_io_channel_unref(captive_vfs_parent_object->corba_parent_giochanel_blind);
205         captive_vfs_parent_object->corba_parent_giochanel_blind=NULL;
206
207         if (captive_vfs_parent_object->corba_bug_doc) {
208                 xmlFreeDoc(captive_vfs_parent_object->corba_bug_doc);
209                 captive_vfs_parent_object->corba_bug_doc=NULL;
210                 captive_vfs_parent_object->corba_bug=NULL;
211                 captive_vfs_parent_object->corba_bug_action=NULL;
212                 captive_vfs_parent_object->corba_bug_log=NULL;
213                 }
214
215         return r;
216 }
217
218
219 GnomeVFSResult captive_sandbox_parent_vfs_close(CaptiveVfsParentObject *captive_vfs_parent_object)
220 {
221         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
222
223         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
224
225         if (captive_vfs_parent_object->corba_bug_action) {
226 xmlNode *xml_action;
227
228                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "vfs_close",NULL);
229                 xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_vfs_parent_object));
230                 }
231
232         return captive_sandbox_parent_vfs_close_silent(captive_vfs_parent_object);
233 }
234
235
236 GnomeVFSResult captive_sandbox_parent_vfs_commit(CaptiveVfsParentObject *captive_vfs_parent_object)
237 {
238 GnomeVFSResult r_close,r_new;
239 xmlNode *xml_action=NULL;
240
241         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
242
243         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
244
245         if (captive_vfs_parent_object->corba_bug_action) {
246                 xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "vfs_commit",NULL);
247                 xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_vfs_parent_object));
248                 }
249
250         r_close=captive_vfs_parent_object_disconnect(captive_vfs_parent_object);
251         if (captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL)
252                 r_new=captive_vfs_parent_object_connect(captive_vfs_parent_object);
253         else
254                 r_new=GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE;
255
256         if (captive_vfs_parent_object->corba_bug_action) {
257                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "vfs_commit",NULL);
258                 xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_vfs_parent_object));
259                 xmlNewProp(xml_action,BAD_CAST "result_prev_close",BAD_CAST gnome_vfs_result_to_string(r_close));
260                 xmlNewProp(xml_action,BAD_CAST "result",BAD_CAST gnome_vfs_result_to_string(r_new));
261                 }
262
263         return (r_new!=GNOME_VFS_OK ? r_new : r_close);
264 }
265
266
267 GnomeVFSResult captive_sandbox_parent_vfs_volume_info_get
268                 (CaptiveVfsParentObject *captive_vfs_parent_object,CaptiveVfsVolumeInfo *volume_info_captive)
269 {
270 xmlNode *xml_action=NULL;
271 Captive_CaptiveVfsVolumeInfo volume_info_corba;
272 GnomeVFSResult r;
273
274         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
275         g_return_val_if_fail(volume_info_captive!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
276
277         if (captive_vfs_parent_object->corba_bug_action) {
278                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "vfs_volume_info_get",NULL);
279                 xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_vfs_parent_object));
280                 }
281
282         Captive_Vfs_volume_info_get(captive_vfs_parent_object->corba_Vfs_object,&volume_info_corba,&captive_corba_ev);
283         if (xml_action)
284                 xmlNewProp(xml_action,BAD_CAST "result",BAD_CAST (captive_corba_ev._major==CORBA_NO_EXCEPTION ? "1" : "0"));
285
286         r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object);
287         if (xml_action)
288                 xmlSetProp(xml_action,BAD_CAST "result",BAD_CAST gnome_vfs_result_to_string(r));
289         if (r!=GNOME_VFS_OK)
290                 return r;
291
292         volume_info_captive->block_size=volume_info_corba.block_size;
293         volume_info_captive->bytes=volume_info_corba.bytes;
294         volume_info_captive->bytes_free=volume_info_corba.bytes_free;
295         volume_info_captive->bytes_available=volume_info_corba.bytes_available;
296
297         return GNOME_VFS_OK;
298 }