Implemented CaptiveParentConnector sandbox restarts handling GInterface.
[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 static 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,"vfs_new",NULL);
68                 xmlNewProp(xml_action,"object",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;
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,"type",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         /* Always clear 'corba_Vfs_object' even if 'r' means failure. */
128         CORBA_Object_release(captive_vfs_parent_object->corba_Vfs_object,&captive_corba_ev);
129         g_assert(validate_CORBA_Environment(&captive_corba_ev));
130         captive_vfs_parent_object->corba_Vfs_object=CORBA_OBJECT_NIL;
131
132         /* Shutdown 'GLogFunc' servant. */
133         GLogFunc_servant=PortableServer_POA_reference_to_servant(captive_corba_poa,
134                         captive_vfs_parent_object->corba_GLogFunc_object,&captive_corba_ev);
135         g_assert(validate_CORBA_Environment(&captive_corba_ev));
136         CORBA_Object_release(captive_vfs_parent_object->corba_GLogFunc_object,&captive_corba_ev);
137         g_assert(validate_CORBA_Environment(&captive_corba_ev));
138         impl_Captive_GLogFunc__destroy(GLogFunc_servant,&captive_corba_ev);
139         g_assert(validate_CORBA_Environment(&captive_corba_ev));
140
141         /* Shutdown 'CaptiveIOChannel' servant. */
142         CaptiveIOChannel_servant=PortableServer_POA_reference_to_servant(captive_corba_poa,
143                         captive_vfs_parent_object->corba_CaptiveIOChannel_object,&captive_corba_ev);
144         g_assert(validate_CORBA_Environment(&captive_corba_ev));
145         CORBA_Object_release(captive_vfs_parent_object->corba_CaptiveIOChannel_object,&captive_corba_ev);
146         g_assert(validate_CORBA_Environment(&captive_corba_ev));
147         impl_Captive_CaptiveIOChannel__destroy(CaptiveIOChannel_servant,&captive_corba_ev);
148         g_assert(validate_CORBA_Environment(&captive_corba_ev));
149
150         /* Close parentheart_fd_write. */
151         if (captive_vfs_parent_object->corba_parentheart_fds_1!=-1) {
152                 errint=close(captive_vfs_parent_object->corba_parentheart_fds_1);
153                 g_return_val_if_fail(errint==0,FALSE);
154                 }
155
156         /* Cleanup the child process. */
157         if (captive_vfs_parent_object->corba_child_pid!=(pid_t)-1) {
158                 kill(captive_vfs_parent_object->corba_child_pid,SIGKILL);       /* errors ignored */
159                 /* waitpid(2) errors are ignored as we should be immune against failures as the parent. */
160                 waitpid(captive_vfs_parent_object->corba_child_pid,
161                                 NULL,   /* status */
162                                 WNOHANG);       /* options */
163                 }
164
165         if (r==GNOME_VFS_OK) {
166                 erriostatus=captive_giochannel_blind_commit(captive_vfs_parent_object->corba_parent_giochanel_blind);
167                 g_assert(erriostatus==G_IO_STATUS_NORMAL);
168                 }
169         else {  /* sandbox child failure */
170                 /* Flush the channel to catch all the disk accesses to the bugreport. */
171                 erriostatus=g_io_channel_flush(
172                                 captive_vfs_parent_object->corba_parent_giochanel_blind,        /* channel */
173                                 NULL);  /* error */
174                 g_assert(erriostatus==G_IO_STATUS_NORMAL);
175
176                 /* Summarize the bugreport. */
177                 if (captive_vfs_parent_object->corba_bug_doc)
178                         bug_doc_generate(captive_vfs_parent_object);
179                 }
180         g_io_channel_unref(captive_vfs_parent_object->corba_parent_giochanel_blind);
181         captive_vfs_parent_object->corba_parent_giochanel_blind=NULL;
182
183         if (captive_vfs_parent_object->corba_bug_doc) {
184                 xmlFreeDoc(captive_vfs_parent_object->corba_bug_doc);
185                 captive_vfs_parent_object->corba_bug_doc=NULL;
186                 captive_vfs_parent_object->corba_bug=NULL;
187                 captive_vfs_parent_object->corba_bug_action=NULL;
188                 captive_vfs_parent_object->corba_bug_log=NULL;
189                 }
190
191         return r;
192 }
193
194
195 GnomeVFSResult captive_sandbox_parent_vfs_close(CaptiveVfsParentObject *captive_vfs_parent_object)
196 {
197         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
198
199         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
200
201         if (captive_vfs_parent_object->corba_bug_action) {
202 xmlNode *xml_action;
203
204                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,"vfs_close",NULL);
205                 xmlNewProp(xml_action,"object",captive_printf_alloca("%p",captive_vfs_parent_object));
206                 }
207
208         return captive_sandbox_parent_vfs_close_silent(captive_vfs_parent_object);
209 }
210
211
212 GnomeVFSResult captive_sandbox_parent_vfs_commit(CaptiveVfsParentObject *captive_vfs_parent_object)
213 {
214 GnomeVFSResult r_close,r_new;
215 xmlNode *xml_action=NULL;
216
217         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
218
219         g_return_val_if_fail(captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL,GNOME_VFS_ERROR_BAD_PARAMETERS);
220
221         if (captive_vfs_parent_object->corba_bug_action) {
222                 xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,"vfs_commit",NULL);
223                 xmlNewProp(xml_action,"object",captive_printf_alloca("%p",captive_vfs_parent_object));
224                 }
225
226         r_close=captive_vfs_parent_object_disconnect(captive_vfs_parent_object);
227         if (captive_vfs_parent_object->corba_Vfs_object==CORBA_OBJECT_NIL)
228                 r_new=captive_vfs_parent_object_connect(captive_vfs_parent_object);
229         else
230                 r_new=GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE;
231
232         if (captive_vfs_parent_object->corba_bug_action) {
233                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,"vfs_commit",NULL);
234                 xmlNewProp(xml_action,"object",captive_printf_alloca("%p",captive_vfs_parent_object));
235                 xmlNewProp(xml_action,"result_prev_close",gnome_vfs_result_to_string(r_close));
236                 xmlNewProp(xml_action,"result",gnome_vfs_result_to_string(r_new));
237                 }
238
239         return (r_new!=GNOME_VFS_OK ? r_new : r_close);
240 }
241
242
243 GnomeVFSResult captive_sandbox_parent_vfs_volume_info_get
244                 (CaptiveVfsParentObject *captive_vfs_parent_object,CaptiveVfsVolumeInfo *volume_info_captive)
245 {
246 xmlNode *xml_action=NULL;
247 Captive_CaptiveVfsVolumeInfo volume_info_corba;
248 GnomeVFSResult r;
249
250         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
251         g_return_val_if_fail(volume_info_captive!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
252
253         if (captive_vfs_parent_object->corba_bug_action) {
254                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,"vfs_volume_info_get",NULL);
255                 xmlNewProp(xml_action,"object",captive_printf_alloca("%p",captive_vfs_parent_object));
256                 }
257
258         Captive_Vfs_volume_info_get(captive_vfs_parent_object->corba_Vfs_object,&volume_info_corba,&captive_corba_ev);
259         if (xml_action)
260                 xmlNewProp(xml_action,"result",(captive_corba_ev._major==CORBA_NO_EXCEPTION ? "1" : "0"));
261
262         r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object);
263         if (xml_action)
264                 xmlSetProp(xml_action,"result",gnome_vfs_result_to_string(r));
265         if (r!=GNOME_VFS_OK)
266                 return r;
267
268         volume_info_captive->block_size=volume_info_corba.block_size;
269         volume_info_captive->bytes=volume_info_corba.bytes;
270         volume_info_captive->bytes_free=volume_info_corba.bytes_free;
271         volume_info_captive->bytes_available=volume_info_corba.bytes_available;
272
273         return GNOME_VFS_OK;
274 }