648b9071f4844f03bc83ba45fc6320546a87e6c2
[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         errbool=captive_sandbox_spawn(captive_vfs_parent_object);
46         g_return_val_if_fail(errbool==TRUE,GNOME_VFS_ERROR_GENERIC);
47
48         return GNOME_VFS_OK;
49 }
50
51
52 GnomeVFSResult captive_sandbox_parent_vfs_new(CaptiveVfsParentObject *captive_vfs_parent_object)
53 {
54 GnomeVFSResult r;
55
56         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
57
58         r=captive_sandbox_parent_vfs_new_silent(captive_vfs_parent_object);
59
60         if (captive_vfs_parent_object->corba_bug_action) {
61 xmlNode *xml_action;
62
63                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,"vfs_new",NULL);
64                 xmlNewProp(xml_action,"object",captive_printf_alloca("%p",captive_vfs_parent_object));
65                 }
66
67         return r;
68 }
69
70
71 static void bug_doc_generate(CaptiveVfsParentObject *captive_vfs_parent_object)
72 {
73 size_t out_fname_size;
74 time_t time_t_local;
75 gchar out_fname[PATH_MAX];
76 int errint;
77 xmlNode *xml_media;
78 const gchar *xml_media_type;
79
80         g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
81
82         xml_media=captive_giochannel_blind_readreport_to_xml(captive_vfs_parent_object->corba_bug,captive_vfs_parent_object->corba_parent_giochanel_blind);
83         switch (CAPTIVE_VFS_OBJECT(captive_vfs_parent_object)->options.media) {
84                 case CAPTIVE_OPTION_MEDIA_CDROM: xml_media_type="cdrom"; break;
85                 case CAPTIVE_OPTION_MEDIA_DISK:  xml_media_type="disk";  break;
86                 default: g_assert_not_reached();
87                 }
88         xmlNewProp(xml_media,"type",xml_media_type);
89
90         xmlSetDocCompressMode(captive_vfs_parent_object->corba_bug_doc,9);
91
92         time(&time_t_local);
93         if (!(out_fname_size=strftime(out_fname,sizeof(out_fname),
94                         CAPTIVE_VFS_OBJECT(captive_vfs_parent_object)->options.bug_pathname,localtime(&time_t_local)))) {
95                 g_assert_not_reached();
96                 return;
97                 }
98
99         /* xmlSaveFormatFileEnc() would be better to prevent rewriting
100          * of target 'out_fname' but it does not support compression.
101          */
102         errint=xmlSaveFormatFileEnc(out_fname,captive_vfs_parent_object->corba_bug_doc,"UTF-8",
103                         1);     /* format; ==output indenting; FIXME: Is it really indented? */
104         g_assert(errint!=-1);
105 }
106
107
108 static GnomeVFSResult captive_sandbox_parent_vfs_close_silent(CaptiveVfsParentObject *captive_vfs_parent_object)
109 {
110 GnomeVFSResult r;
111 int errint;
112 impl_POA_Captive_GLogFunc *GLogFunc_servant;
113 impl_POA_Captive_CaptiveIOChannel *CaptiveIOChannel_servant;
114 GIOStatus erriostatus;
115
116         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
117
118         Captive_Vfs_shutdown(captive_vfs_parent_object->corba_Vfs_object,&captive_corba_ev);
119         r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev);
120
121         CORBA_Object_release(captive_vfs_parent_object->corba_Vfs_object,&captive_corba_ev);
122         g_assert(validate_CORBA_Environment(&captive_corba_ev));
123
124         /* Shutdown 'GLogFunc' servant. */
125         GLogFunc_servant=PortableServer_POA_reference_to_servant(captive_corba_poa,
126                         captive_vfs_parent_object->corba_GLogFunc_object,&captive_corba_ev);
127         g_assert(validate_CORBA_Environment(&captive_corba_ev));
128         CORBA_Object_release(captive_vfs_parent_object->corba_GLogFunc_object,&captive_corba_ev);
129         g_assert(validate_CORBA_Environment(&captive_corba_ev));
130         impl_Captive_GLogFunc__destroy(GLogFunc_servant,&captive_corba_ev);
131         g_assert(validate_CORBA_Environment(&captive_corba_ev));
132
133         /* Shutdown 'CaptiveIOChannel' servant. */
134         CaptiveIOChannel_servant=PortableServer_POA_reference_to_servant(captive_corba_poa,
135                         captive_vfs_parent_object->corba_CaptiveIOChannel_object,&captive_corba_ev);
136         g_assert(validate_CORBA_Environment(&captive_corba_ev));
137         CORBA_Object_release(captive_vfs_parent_object->corba_CaptiveIOChannel_object,&captive_corba_ev);
138         g_assert(validate_CORBA_Environment(&captive_corba_ev));
139         impl_Captive_CaptiveIOChannel__destroy(CaptiveIOChannel_servant,&captive_corba_ev);
140         g_assert(validate_CORBA_Environment(&captive_corba_ev));
141
142         /* Close parentheart_fd_write. */
143         if (captive_vfs_parent_object->corba_parentheart_fds_1!=-1) {
144                 errint=close(captive_vfs_parent_object->corba_parentheart_fds_1);
145                 g_return_val_if_fail(errint==0,FALSE);
146                 }
147
148         /* Cleanup the child process. */
149         if (captive_vfs_parent_object->corba_child_pid!=(pid_t)-1) {
150                 kill(captive_vfs_parent_object->corba_child_pid,SIGKILL);       /* errors ignored */
151                 /* waitpid(2) errors are ignored as we should be immune against failures as the parent. */
152                 waitpid(captive_vfs_parent_object->corba_child_pid,
153                                 NULL,   /* status */
154                                 WNOHANG);       /* options */
155                 }
156
157         if (r==GNOME_VFS_OK) {
158                 erriostatus=captive_giochannel_blind_commit(captive_vfs_parent_object->corba_parent_giochanel_blind);
159                 g_assert(erriostatus==G_IO_STATUS_NORMAL);
160                 }
161         else {  /* sandbox child failure */
162                 /* Flush the channel to catch all the disk accesses to the bugreport. */
163                 erriostatus=g_io_channel_flush(
164                                 captive_vfs_parent_object->corba_parent_giochanel_blind,        /* channel */
165                                 NULL);  /* error */
166                 g_assert(erriostatus==G_IO_STATUS_NORMAL);
167
168                 /* Summarize the bugreport. */
169                 if (captive_vfs_parent_object->corba_bug_doc)
170                         bug_doc_generate(captive_vfs_parent_object);
171                 }
172         g_io_channel_unref(captive_vfs_parent_object->corba_parent_giochanel_blind);
173         captive_vfs_parent_object->corba_parent_giochanel_blind=NULL;
174
175         if (captive_vfs_parent_object->corba_bug_doc) {
176                 xmlFreeDoc(captive_vfs_parent_object->corba_bug_doc);
177                 captive_vfs_parent_object->corba_bug_doc=NULL;
178                 captive_vfs_parent_object->corba_bug=NULL;
179                 captive_vfs_parent_object->corba_bug_action=NULL;
180                 captive_vfs_parent_object->corba_bug_log=NULL;
181                 }
182
183         return r;
184 }
185
186
187 GnomeVFSResult captive_sandbox_parent_vfs_close(CaptiveVfsParentObject *captive_vfs_parent_object)
188 {
189         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
190
191         if (captive_vfs_parent_object->corba_bug_action) {
192 xmlNode *xml_action;
193
194                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,"vfs_close",NULL);
195                 xmlNewProp(xml_action,"object",captive_printf_alloca("%p",captive_vfs_parent_object));
196                 }
197
198         return captive_sandbox_parent_vfs_close_silent(captive_vfs_parent_object);
199 }
200
201
202 GnomeVFSResult captive_sandbox_parent_vfs_commit(CaptiveVfsParentObject *captive_vfs_parent_object)
203 {
204 GnomeVFSResult r_close,r_new;
205 xmlNode *xml_action=NULL;
206
207         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
208
209         if (captive_vfs_parent_object->corba_bug_action) {
210                 xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,"vfs_commit",NULL);
211                 xmlNewProp(xml_action,"object",captive_printf_alloca("%p",captive_vfs_parent_object));
212                 }
213
214         r_close=captive_sandbox_parent_vfs_close_silent(captive_vfs_parent_object);     /* errors ignored */
215         r_new=captive_sandbox_parent_vfs_new_silent(captive_vfs_parent_object);
216
217         if (captive_vfs_parent_object->corba_bug_action) {
218                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,"vfs_commit",NULL);
219                 xmlNewProp(xml_action,"object",captive_printf_alloca("%p",captive_vfs_parent_object));
220                 xmlNewProp(xml_action,"result_prev_close",gnome_vfs_result_to_string(r_close));
221                 xmlNewProp(xml_action,"result",gnome_vfs_result_to_string(r_new));
222                 }
223
224         return (r_new!=GNOME_VFS_OK ? r_new : r_close);
225 }
226
227
228 GnomeVFSResult captive_sandbox_parent_vfs_volume_info_get
229                 (CaptiveVfsParentObject *captive_vfs_parent_object,CaptiveVfsVolumeInfo *volume_info_captive)
230 {
231 xmlNode *xml_action;
232 Captive_CaptiveVfsVolumeInfo volume_info_corba;
233 GnomeVFSResult r;
234 gboolean retried=FALSE;
235
236         g_return_val_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
237         g_return_val_if_fail(volume_info_captive!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
238
239 retry:
240         xml_action=NULL;
241         if (captive_vfs_parent_object->corba_bug_action) {
242                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,"vfs_volume_info_get",NULL);
243                 xmlNewProp(xml_action,"object",captive_printf_alloca("%p",captive_vfs_parent_object));
244                 }
245
246         Captive_Vfs_volume_info_get(captive_vfs_parent_object->corba_Vfs_object,&volume_info_corba,&captive_corba_ev);
247         if (xml_action)
248                 xmlNewProp(xml_action,"result",(captive_corba_ev._major==CORBA_NO_EXCEPTION ? "1" : "0"));
249
250         if (!retried && captive_sandbox_parent_query_vfs_retry(&captive_corba_ev,captive_vfs_parent_object)) {
251                 retried=TRUE;
252                 goto retry;
253                 }
254
255         r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev);
256         if (xml_action)
257                 xmlSetProp(xml_action,"result",gnome_vfs_result_to_string(r));
258         if (r!=GNOME_VFS_OK)
259                 return r;
260
261         volume_info_captive->block_size=volume_info_corba.block_size;
262         volume_info_captive->bytes=volume_info_corba.bytes;
263         volume_info_captive->bytes_free=volume_info_corba.bytes_free;
264         volume_info_captive->bytes_available=volume_info_corba.bytes_available;
265
266         return GNOME_VFS_OK;
267 }