#include "split.h" /* self */
#include "sandbox.h"
-#include "server-GlibLogFunc.h"
+#include "server-GLogFunc.h"
#include "captive/macros.h"
#include <glib/gmacros.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <linc/linc.h> /* for linc_main_get_loop() */
-#include "server-GlibLogFunc.h"
#include "server-Directory.h"
#include "server-Vfs.h"
#include "../client/vfs.h"
+#include "captive/parent-Vfs.h"
+#include <dirent.h>
+#include "server-CaptiveIOChannel.h"
+#include <errno.h>
/* CONFIG: */
#define HEARTBEAT_SOURCE_CHECK_REVENTS (HEARTBEAT_SOURCE_CHECK_EVENTS|G_IO_ERR|G_IO_HUP|G_IO_NVAL)
-gboolean validate_CORBA_Environment(const CORBA_Environment *evp)
+gboolean validate_CORBA_Environment(CORBA_Environment *evp)
{
- g_return_val_if_fail(evp->_major==CORBA_NO_EXCEPTION,FALSE);
+ if (evp->_major==CORBA_NO_EXCEPTION)
+ return TRUE;
- return TRUE;
+ g_message(_("CORBA Exception occured: id=\"%s\", value=%p"),
+ CORBA_exception_id(evp),CORBA_exception_value(evp));
+ return FALSE;
}
CORBA_Environment captive_corba_ev;
}
+static GSource *captive_corba_sandbox_child_heartbeat_gsource;
+
+void sandbox_child_prepare_shutdown(void)
+{
+ /* Prevent during shutdown: Captive-WARNING **: CORBA Exception occured: id="IDL:omg.org/CORBA/COMM_FAILURE:1.0" */
+ if (captive_corba_sandbox_child_heartbeat_gsource) {
+ g_source_destroy(captive_corba_sandbox_child_heartbeat_gsource);
+ g_source_unref(captive_corba_sandbox_child_heartbeat_gsource);
+ captive_corba_sandbox_child_heartbeat_gsource=NULL;
+ }
+}
+
+
void sandbox_child_shutdown(void)
{
/* Do not fail by passing logging messages to the master. */
- impl_Captive_Vfs_registerGlibLogFunc_disable();
+ impl_Captive_Vfs_init_g_log_func_disable();
g_main_loop_quit(linc_main_get_loop());
}
}
-static void sandbox_child(int Vfs_IOR_fd_write,GSource *gsource,CaptiveVfsObject *child_captive_vfs_object) G_GNUC_NORETURN;
-static void sandbox_child(int Vfs_IOR_fd_write,GSource *gsource,CaptiveVfsObject *child_captive_vfs_object)
+static gboolean heartbeat_source_prepare(GSource *source,gint *timeout)
+{
+ *timeout=-1;
+
+ return FALSE;
+}
+
+static GPollFD heartbeat_source_check_gpollfd;
+
+static gboolean heartbeat_source_check(GSource *source)
+{
+ return !!(heartbeat_source_check_gpollfd.revents & HEARTBEAT_SOURCE_CHECK_REVENTS);
+}
+
+static gboolean heartbeat_source_dispatch(GSource *source,GSourceFunc callback,gpointer user_data)
+{
+ g_assert(callback!=NULL);
+ return (*callback)(user_data);
+}
+
+static GSourceFuncs heartbeat_source_watch_funcs={
+ heartbeat_source_prepare,
+ heartbeat_source_check,
+ heartbeat_source_dispatch,
+ NULL, /* finalize */
+ };
+
+void captive_corba_sandbox_child(void)
{
Captive_Vfs Vfs_object;
+impl_POA_Captive_Vfs *Vfs_servant;
gboolean errbool;
int errint;
guint errguint;
+GSource *gsource;
- errint=close(0); /* STDIN */
- g_assert(errint==0);
- errint=close(1); /* STDOUT */
- g_assert(errint==0);
- errint=close(2); /* STDERR */
- g_assert(errint==0);
+ /* attach heartbeat_source_callback() to watch for any abnormalities
+ * on our open pipe 'parentheart_fds' and terminate the child if parent dies.
+ */
+ gsource=g_source_new(&heartbeat_source_watch_funcs,sizeof(GSource));
+ g_return_if_fail(gsource!=NULL);
+ g_source_set_callback(
+ gsource, /* source */
+ heartbeat_source_callback, /* func */
+ NULL, /* data */
+ NULL); /* notify */
+ heartbeat_source_check_gpollfd.fd=0 /* STDIN */; /* parentheart_fd_read */
+ heartbeat_source_check_gpollfd.events=HEARTBEAT_SOURCE_CHECK_EVENTS;
+ heartbeat_source_check_gpollfd.revents=0;
+ g_source_add_poll(gsource,&heartbeat_source_check_gpollfd);
- g_assert(captive_corba_child_options==NULL);
- captive_corba_child_options=&child_captive_vfs_object->options;
+ errbool=corba_init("captive-sandbox-child",&captive_corba_ev,&captive_corba_orb,&captive_corba_poa);
+ g_return_if_fail(errbool==TRUE);
heartbeat_source_callback_orb=captive_corba_orb;
Vfs_IOR=CORBA_ORB_object_to_string(captive_corba_orb,Vfs_object,&captive_corba_ev);
g_assert(validate_CORBA_Environment(&captive_corba_ev));
g_assert(Vfs_IOR!=NULL);
- errint=write(Vfs_IOR_fd_write,Vfs_IOR,strlen(Vfs_IOR)+1);
+ errint=write(1 /* STDOUT */,Vfs_IOR,strlen(Vfs_IOR)+1);
g_assert((unsigned)errint==strlen(Vfs_IOR)+1);
- errint=close(Vfs_IOR_fd_write);
+ errint=close(1 /* STDOUT */);
g_assert(errint==0);
CORBA_free(Vfs_IOR);
}
g_assert(validate_CORBA_Environment(&captive_corba_ev));
/* Shutdown 'Vfs' servant */
+ Vfs_servant=PortableServer_POA_reference_to_servant(captive_corba_poa,Vfs_object,&captive_corba_ev);
+ g_assert(validate_CORBA_Environment(&captive_corba_ev));
CORBA_Object_release(Vfs_object,&captive_corba_ev);
g_assert(validate_CORBA_Environment(&captive_corba_ev));
+ impl_Captive_Vfs__destroy(Vfs_servant,&captive_corba_ev);
+ g_assert(validate_CORBA_Environment(&captive_corba_ev));
errbool=corba_shutdown(&captive_corba_ev,&captive_corba_orb,&captive_corba_poa);
g_assert(errbool==TRUE);
_exit(EXIT_SUCCESS);
}
-static void sandbox_parent
- (int Vfs_IOR_fd_read,Captive_Vfs *corba_Vfs_object_return,Captive_GlibLogFunc *corba_GlibLogFunc_object_return)
+
+static void options_module_captive_to_options_module_corba
+ (Captive_CaptiveOptionsModule *dest_options_module_corba,const struct captive_options_module *src_options_module_captive)
+{
+ g_return_if_fail(dest_options_module_corba!=NULL);
+ g_return_if_fail(src_options_module_captive!=NULL);
+
+ g_return_if_fail(src_options_module_captive->type==CAPTIVE_OPTIONS_MODULE_TYPE_PE32);
+
+ dest_options_module_corba->pathname_utf8=g_strdup(src_options_module_captive->pathname_utf8);
+ dest_options_module_corba->data._buffer=g_memdup(src_options_module_captive->u.pe32.base,
+ src_options_module_captive->u.pe32.length);
+ dest_options_module_corba->data._maximum=src_options_module_captive->u.pe32.length;
+ dest_options_module_corba->data._length =src_options_module_captive->u.pe32.length;
+ dest_options_module_corba->data._release=TRUE;
+}
+
+
+static void sandbox_parent(const char *Vfs_IOR,struct captive_options *options_captive,Captive_Vfs *corba_Vfs_object_return,
+ Captive_GLogFunc *corba_GLogFunc_object_return,Captive_CaptiveIOChannel *corba_CaptiveIOChannel_object_return)
{
-char *Vfs_IOR;
-gsize Vfs_IOR_size;
Captive_Vfs Vfs_object;
-Captive_GlibLogFunc GlibLogFunc_object;
-int errint;
+Captive_GLogFunc GLogFunc_object;
+Captive_CaptiveIOChannel CaptiveIOChannel_object;
+Captive_CaptiveOptions options_corba;
+guint load_module_length,load_moduleui;
+struct captive_options_module *options_module;
+gboolean errbool;
+GList *load_module_node;
- g_return_if_fail(Vfs_IOR_fd_read!=-1);
+ g_return_if_fail(Vfs_IOR!=NULL);
g_return_if_fail(corba_Vfs_object_return!=NULL);
- g_return_if_fail(corba_GlibLogFunc_object_return!=NULL);
+ g_return_if_fail(corba_GLogFunc_object_return!=NULL);
- Vfs_IOR=captive_rtl_file_read(Vfs_IOR_fd_read,&Vfs_IOR_size);
- g_assert(Vfs_IOR!=NULL);
- g_assert(Vfs_IOR_size>=1);
- g_assert(memchr(Vfs_IOR,0,Vfs_IOR_size)==Vfs_IOR+(Vfs_IOR_size-1)); /* check exactly for 0-terminated string */
- errint=close(Vfs_IOR_fd_read);
- g_assert(errint==0);
+ errbool=corba_init("captive-sandbox-parent",&captive_corba_ev,&captive_corba_orb,&captive_corba_poa);
+ g_assert(errbool==TRUE);
Vfs_object=CORBA_ORB_string_to_object(captive_corba_orb,Vfs_IOR,&captive_corba_ev);
g_assert(validate_CORBA_Environment(&captive_corba_ev));
- g_free(Vfs_IOR);
- /* Init 'GlibLogFunc_object' */
- GlibLogFunc_object=impl_Captive_GlibLogFunc__create(captive_corba_poa,&captive_corba_ev);
+ /* Init 'GLogFunc_object' */
+ GLogFunc_object=impl_Captive_GLogFunc__create(captive_corba_poa,&captive_corba_ev);
+ g_assert(validate_CORBA_Environment(&captive_corba_ev));
+
+ /* Init 'CaptiveIOChannel_object' */
+ CaptiveIOChannel_object=impl_Captive_CaptiveIOChannel__create(captive_corba_poa,
+ options_captive->image_iochannel,&captive_corba_ev);
g_assert(validate_CORBA_Environment(&captive_corba_ev));
- Captive_Vfs_registerGlibLogFunc(Vfs_object,GlibLogFunc_object,&captive_corba_ev);
+
+ options_corba.g_log_func=GLogFunc_object;
+ options_module_captive_to_options_module_corba(&options_corba.filesystem,&options_captive->filesystem);
+ options_corba.rwmode =options_captive->rwmode;
+ options_corba.media =options_captive->media;
+ options_corba.debug_messages=options_captive->debug_messages;
+ options_corba.image_iochannel=CaptiveIOChannel_object;
+
+ load_module_length=g_list_length(options_captive->load_module);
+ captive_newn(options_corba.load_module._buffer,load_module_length);
+ options_corba.load_module._maximum=load_module_length;
+ options_corba.load_module._length=load_module_length;
+ options_corba.load_module._release=TRUE;
+ for (load_moduleui=0,load_module_node=options_captive->load_module;
+ load_module_node;
+ load_moduleui++,load_module_node=load_module_node->next) {
+ options_module=load_module_node->data;
+ options_module_captive_to_options_module_corba(options_corba.load_module._buffer+load_moduleui,options_module);
+ }
+
+ Captive_Vfs_init(Vfs_object,&options_corba,&captive_corba_ev);
g_assert(validate_CORBA_Environment(&captive_corba_ev));
+ /* FIXME: Free 'options_corba' - LEAK */
+
*corba_Vfs_object_return=Vfs_object;
- *corba_GlibLogFunc_object_return=GlibLogFunc_object;
+ *corba_GLogFunc_object_return=GLogFunc_object;
+ *corba_CaptiveIOChannel_object_return=CaptiveIOChannel_object;
}
-static gboolean heartbeat_source_prepare(GSource *source,gint *timeout)
+static void fd_shiftup(int *fdp)
{
- *timeout=-1;
+ g_return_if_fail(fdp!=NULL);
- return FALSE;
+ while (*fdp<=2 /* STDERR */) {
+ *fdp=dup(*fdp);
+ g_assert(*fdp!=-1);
+ }
}
-static GPollFD heartbeat_source_check_gpollfd;
-
-static gboolean heartbeat_source_check(GSource *source)
+void captive_sandbox_fd_closeup(int fd_first_to_delete)
{
- return !!(heartbeat_source_check_gpollfd.revents & HEARTBEAT_SOURCE_CHECK_REVENTS);
-}
+DIR *dir;
+int errint;
+int dir_fd;
+struct dirent *dirent;
+
+ dir=opendir("/proc/self/fd/");
+ g_return_if_fail(dir!=NULL);
+ dir_fd=dirfd(dir);
+ g_return_if_fail(dir_fd!=-1);
+
+ while (errno=0,(dirent=readdir(dir))) {
+long dirent_fd;
+char *endptr;
+
+ if (0
+ || !strcmp(dirent->d_name,".")
+ || !strcmp(dirent->d_name,".."))
+ continue;
+ dirent_fd=strtol(dirent->d_name,&endptr,10 /* base */);
+ g_assert(dirent_fd>=0 && (!endptr || !*endptr));
+ if (dirent_fd<fd_first_to_delete || dirent_fd==dir_fd)
+ continue;
+
+ errint=close(dirent_fd);
+ g_assert(errint==0);
+ errno=0;
+ errint=close(dirent_fd);
+ g_assert(errint==-1); g_assert(errno==EBADF);
+ }
+ g_return_if_fail(errno==0); /* check for EOF */
-static gboolean heartbeat_source_dispatch(GSource *source,GSourceFunc callback,gpointer user_data)
-{
- g_assert(callback!=NULL);
- return (*callback)(user_data);
+ errint=closedir(dir);
+ g_return_if_fail(errint==0);
+ errno=0;
+ close(dir_fd); g_assert(errno==EBADF); /* just a bit of paranoia; it should be already closed by closedir() */
}
-static GSourceFuncs heartbeat_source_watch_funcs={
- heartbeat_source_prepare,
- heartbeat_source_check,
- heartbeat_source_dispatch,
- NULL, /* finalize */
- };
-
-
gboolean captive_sandbox_spawn(CaptiveVfsObject *child_captive_vfs_object,
- Captive_Vfs *corba_Vfs_object_return,Captive_GlibLogFunc *corba_GlibLogFunc_object_return,int *parentheart_fds_1_return)
+ Captive_Vfs *corba_Vfs_object_return,Captive_GLogFunc *corba_GLogFunc_object_return,
+ Captive_CaptiveIOChannel *corba_CaptiveIOChannel_object_return,int *parentheart_fds_1_return)
{
/* Vfs_IOR_fds[0] for reading by sandbox_parent() - client,
* Vfs_IOR_fds[1] for writing by sandbox_child() - server
*/
int Vfs_IOR_fds[2],parentheart_fds[2];
int errint;
-gboolean errbool;
g_return_val_if_fail(child_captive_vfs_object!=NULL,FALSE);
g_return_val_if_fail(corba_Vfs_object_return!=NULL,FALSE);
- g_return_val_if_fail(corba_GlibLogFunc_object_return!=NULL,FALSE);
+ g_return_val_if_fail(corba_GLogFunc_object_return!=NULL,FALSE);
g_return_val_if_fail(parentheart_fds_1_return!=NULL,FALSE);
errint=pipe(Vfs_IOR_fds);
errint=pipe(parentheart_fds);
g_return_val_if_fail(errint==0,FALSE);
- /* We cannot initialize 'parent' and 'child' name specifically as
- * we need to have persistence master and its children will be already
- * CORBA-initialized during their spawn.
- */
- errbool=corba_init("captive-sandbox",&captive_corba_ev,&captive_corba_orb,&captive_corba_poa);
- g_return_val_if_fail(errbool==TRUE,FALSE);
-
/* Currently never called anywhere:
* errbool=corba_shutdown(&captive_corba_ev,&captive_corba_orb,&captive_corba_poa);
* g_assert(errbool==TRUE);
*/
+ if (captive_sandbox_server_ior) {
+ *parentheart_fds_1_return=-1;
+ sandbox_parent(
+ captive_sandbox_server_ior, /* Vfs_IOR */
+ &child_captive_vfs_object->options, /* options_captive */
+ corba_Vfs_object_return, /* corba_Vfs_object_return */
+ corba_GLogFunc_object_return, /* corba_GLogFunc_object_return */
+ corba_CaptiveIOChannel_object_return); /* corba_CaptiveIOChannel_object_return */
+ return TRUE;
+ }
+
+ g_assert(captive_sandbox_server_argv!=NULL);
switch (fork()) {
case -1: /* error */
g_return_val_if_reached(FALSE);
case 0: { /* child */
-GSource *gsource;
errint=close(Vfs_IOR_fds[0]); /* close Vfs_IOR_fd_read */
g_return_val_if_fail(errint==0,FALSE);
errint=close(parentheart_fds[1]); /* close parentheart_fd_write */
g_return_val_if_fail(errint==0,FALSE);
- /* attach heartbeat_source_callback() to watch for any abnormalities
- * on our open pipe 'parentheart_fds' and terminate the child if parent dies.
- */
- gsource=g_source_new(&heartbeat_source_watch_funcs,sizeof(GSource));
- g_return_val_if_fail(gsource!=NULL,FALSE);
- g_source_set_callback(
- gsource, /* source */
- heartbeat_source_callback, /* func */
- NULL, /* data */
- NULL); /* notify */
- heartbeat_source_check_gpollfd.fd=parentheart_fds[0]; /* parentheart_fd_read */
- heartbeat_source_check_gpollfd.events=HEARTBEAT_SOURCE_CHECK_EVENTS;
- heartbeat_source_check_gpollfd.revents=0;
- g_source_add_poll(gsource,&heartbeat_source_check_gpollfd);
- sandbox_child(Vfs_IOR_fds[1],gsource,child_captive_vfs_object); /* pass Vfs_IOR_fd_write */
+ fd_shiftup(Vfs_IOR_fds+1); /* Vfs_IOR_fd_write */
+ fd_shiftup(parentheart_fds+0); /* parentheart_fd_read */
+ errint=dup2(Vfs_IOR_fds[1],1 /* STDOUT */); /* Vfs_IOR_fd_write */
+ g_return_val_if_fail(errint==1 /* STDOUT */,FALSE);
+ errint=dup2(parentheart_fds[0],0 /* STDIN */); /* parentheart_fd_read */
+ g_return_val_if_fail(errint==0 /* STDIN */,FALSE);
+
+ captive_sandbox_fd_closeup(2 /* STDERR */ +1);
+
+ execv(captive_sandbox_server_argv[0],/* re-const */ (char * const *)captive_sandbox_server_argv);
g_return_val_if_reached(FALSE);
} /* NOTREACHED */
- default: /* parent */
+ default: { /* parent */
+char *Vfs_IOR;
+gsize Vfs_IOR_size;
+
errint=close(Vfs_IOR_fds[1]); /* close Vfs_IOR_fd_write */
g_return_val_if_fail(errint==0,FALSE);
errint=close(parentheart_fds[0]); /* close parentheart_fd_read */
*/
g_return_val_if_fail(errint==0,FALSE);
*parentheart_fds_1_return=parentheart_fds[1];
+
+ Vfs_IOR=captive_rtl_file_read(Vfs_IOR_fds[0],&Vfs_IOR_size); /* Vfs_IOR_fd_read */
+ g_assert(Vfs_IOR!=NULL);
+ g_assert(Vfs_IOR_size>=1);
+ g_assert(memchr(Vfs_IOR,0,Vfs_IOR_size)==Vfs_IOR+(Vfs_IOR_size-1)); /* check exactly for 0-terminated string */
+ errint=close(Vfs_IOR_fds[0]); /* Vfs_IOR_fd_read */
+ g_assert(errint==0);
+
sandbox_parent(
- Vfs_IOR_fds[0], /* Vfs_IOR_fd_read */
+ Vfs_IOR, /* Vfs_IOR */
+ &child_captive_vfs_object->options, /* options_captive */
corba_Vfs_object_return, /* corba_Vfs_object_return */
- corba_GlibLogFunc_object_return); /* corba_GlibLogFunc_object_return */
+ corba_GLogFunc_object_return, /* corba_GLogFunc_object_return */
+ corba_CaptiveIOChannel_object_return); /* corba_CaptiveIOChannel_object_return */
+
+ g_free(Vfs_IOR);
+
/* 'parentheart_fds[1]' - parentheart_fd_write - is left open here */
return TRUE;
+ }
}
/* NOTREACHED */
g_return_val_if_reached(FALSE);
if (evp->_major==CORBA_NO_EXCEPTION)
return GNOME_VFS_OK;
- if (!strcmp(ex_Captive_GnomeVFSResultException,CORBA_exception_id(evp)))
+ if (evp->_major==CORBA_USER_EXCEPTION && !strcmp(ex_Captive_GnomeVFSResultException,CORBA_exception_id(evp)))
r=((Captive_GnomeVFSResultException *)CORBA_exception_value(evp))->gnome_vfs_result;
else {
r=GNOME_VFS_ERROR_GENERIC;
}
+gboolean captive_sandbox_parent_query_vfs_retry(CORBA_Environment *evp,CaptiveVfsObject *captive_vfs_object)
+{
+GnomeVFSResult errvfsresult;
+
+ g_return_val_if_fail(evp!=NULL,FALSE);
+ g_return_val_if_fail(captive_vfs_object!=NULL,FALSE);
+
+ /* If !captive_sandbox_server_argv it is captive_sandbox_server_ior
+ * where we cannot do any restart anyway.
+ */
+ if (!captive_sandbox_server_argv
+ || !(evp->_major==CORBA_SYSTEM_EXCEPTION && !strcmp(ex_CORBA_COMM_FAILURE,CORBA_exception_id(evp))))
+ return FALSE; /* no retry */
+ CORBA_exception_free(evp);
+
+ captive_sandbox_parent_vfs_close(captive_vfs_object); /* errors ignored */
+ errvfsresult=captive_sandbox_parent_vfs_new(captive_vfs_object);
+
+ return errvfsresult==GNOME_VFS_OK; /* retry if restart succeeded */
+}
+
+
void captive_sandbox_child_GnomeVFSResultException_throw(CORBA_Environment *evp,GnomeVFSResult errvfsresult)
{
Captive_GnomeVFSResultException *gnome_vfs_result_exception;