+backward image iochannel over CORBA transport to be sandboxable
authorshort <>
Sat, 7 Jun 2003 07:20:01 +0000 (07:20 +0000)
committershort <>
Sat, 7 Jun 2003 07:20:01 +0000 (07:20 +0000)
src/libcaptive/sandbox/client-CaptiveIOChannel.c [new file with mode: 0644]
src/libcaptive/sandbox/client-CaptiveIOChannel.h [new file with mode: 0644]
src/libcaptive/sandbox/server-CaptiveIOChannel.c [new file with mode: 0644]
src/libcaptive/sandbox/server-CaptiveIOChannel.h [new file with mode: 0644]
src/libcaptive/storage/size.c

diff --git a/src/libcaptive/sandbox/client-CaptiveIOChannel.c b/src/libcaptive/sandbox/client-CaptiveIOChannel.c
new file mode 100644 (file)
index 0000000..0b72f4f
--- /dev/null
@@ -0,0 +1,227 @@
+/* $Id$
+ * CORBA/ORBit client side of image GIOChannel object of sandbox_child()
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "config.h"
+
+#include "client-CaptiveIOChannel.h"   /* self */
+#include <glib/gmessages.h>
+#include "split.h"
+#include <string.h>
+#include "captive/macros.h"
+
+
+struct captive_io_channel {
+       GIOChannel iochannel;
+       Captive_CaptiveIOChannel corba_captive_io_channel;
+       };
+
+
+G_LOCK_DEFINE_STATIC(captive_io_channel_funcs);
+static GIOFuncs captive_io_channel_funcs;
+
+
+static gboolean validate_captive_io_channel(struct captive_io_channel *captive_io_channel)
+{
+       g_return_val_if_fail(captive_io_channel!=NULL,FALSE);
+       g_return_val_if_fail(captive_io_channel->corba_captive_io_channel!=NULL,FALSE);
+
+       return TRUE;
+}
+
+
+static GIOStatus captive_io_channel_io_read
+               (GIOChannel *channel,gchar *buffer_captive,gsize count,gsize *bytes_read_return,GError **err)
+{
+struct captive_io_channel *captive_io_channel=(struct captive_io_channel *)channel;
+Captive_Bytes *buffer_corba;
+
+       g_return_val_if_fail(validate_captive_io_channel(captive_io_channel),G_IO_STATUS_ERROR);
+       g_return_val_if_fail(buffer_captive!=NULL,G_IO_STATUS_ERROR);
+       g_return_val_if_fail(bytes_read_return!=NULL,G_IO_STATUS_ERROR);
+
+       *bytes_read_return=0;
+
+       Captive_CaptiveIOChannel_read(captive_io_channel->corba_captive_io_channel,&buffer_corba,count,&captive_corba_ev);
+       if (GNOME_VFS_OK!=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev))
+               return G_IO_STATUS_ERROR;
+
+       g_return_val_if_fail(buffer_corba->_length<=count,G_IO_STATUS_ERROR);
+       memcpy(buffer_captive,buffer_corba->_buffer,buffer_corba->_length);
+       *bytes_read_return=buffer_corba->_length;
+
+       Captive_Bytes__freekids(buffer_corba,NULL/* 'd'; meaning? */);
+       CORBA_free(buffer_corba);
+
+       return (*bytes_read_return == 0 ? G_IO_STATUS_EOF : G_IO_STATUS_NORMAL);
+}
+
+
+static GIOStatus captive_io_channel_io_write
+               (GIOChannel *channel,const gchar *buffer_captive,gsize count,gsize *bytes_written_return,GError **err)
+{
+struct captive_io_channel *captive_io_channel=(struct captive_io_channel *)channel;
+Captive_Bytes buffer_corba_local;
+Captive_GSize bytes_written_corba;
+
+       g_return_val_if_fail(validate_captive_io_channel(captive_io_channel),G_IO_STATUS_ERROR);
+       g_return_val_if_fail(buffer_captive!=NULL,G_IO_STATUS_ERROR);
+       g_return_val_if_fail(bytes_written_return!=NULL,G_IO_STATUS_ERROR);
+
+       *bytes_written_return=0;
+
+       buffer_corba_local._maximum=count;
+       buffer_corba_local._length=count;
+       buffer_corba_local._buffer=(/* de-const */gpointer)buffer_captive;
+       buffer_corba_local._release=FALSE;
+
+       Captive_CaptiveIOChannel_write(captive_io_channel->corba_captive_io_channel,
+                       &buffer_corba_local,&bytes_written_corba,&captive_corba_ev);
+       if (GNOME_VFS_OK!=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev))
+               return G_IO_STATUS_ERROR;
+
+       *bytes_written_return=bytes_written_corba;
+
+       return G_IO_STATUS_NORMAL;
+}
+
+
+static GIOStatus captive_io_channel_io_seek(GIOChannel *channel,gint64 offset,GSeekType type,GError **err)
+{
+struct captive_io_channel *captive_io_channel=(struct captive_io_channel *)channel;
+
+       g_return_val_if_fail(validate_captive_io_channel(captive_io_channel),G_IO_STATUS_ERROR);
+
+       Captive_CaptiveIOChannel_seek(captive_io_channel->corba_captive_io_channel,offset,type,&captive_corba_ev);
+       if (GNOME_VFS_OK!=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev))
+               return G_IO_STATUS_ERROR;
+
+       return G_IO_STATUS_NORMAL;
+}
+
+
+static GIOStatus captive_io_channel_io_close(GIOChannel *channel,GError **err)
+{
+struct captive_io_channel *captive_io_channel=(struct captive_io_channel *)channel;
+
+       g_return_val_if_fail(validate_captive_io_channel(captive_io_channel),G_IO_STATUS_ERROR);
+
+       /* We are not authorized to destroy 'captive_io_channel->corba_captive_io_channel'. */
+       /* flush()? */
+       captive_io_channel->corba_captive_io_channel=NULL;
+
+       return G_IO_STATUS_NORMAL;
+}
+
+
+static GSource* captive_io_channel_io_create_watch(GIOChannel *channel,GIOCondition condition)
+{
+struct captive_io_channel *captive_io_channel=(struct captive_io_channel *)channel;
+
+       g_return_val_if_fail(validate_captive_io_channel(captive_io_channel),NULL);
+
+       g_return_val_if_reached(NULL);  /* FIXME: NOT IMPLEMENTED YET */
+}
+
+
+static void captive_io_channel_io_free(GIOChannel *channel)
+{
+struct captive_io_channel *captive_io_channel=(struct captive_io_channel *)channel;
+
+       /* After captive_io_channel_io_close() 'captive_io_channel'
+        * may be no longer valid for validate_captive_io_channel(captive_io_channel).
+        */
+       g_return_if_fail(captive_io_channel!=NULL);
+
+       g_assert(captive_io_channel->corba_captive_io_channel==NULL);
+
+       g_free(captive_io_channel);
+}
+
+
+static GIOStatus captive_io_channel_io_set_flags(GIOChannel *channel,GIOFlags flags,GError **err)
+{
+struct captive_io_channel *captive_io_channel=(struct captive_io_channel *)channel;
+
+       g_return_val_if_fail(validate_captive_io_channel(captive_io_channel),G_IO_STATUS_ERROR);
+
+       /* no G_IO_FLAG_APPEND and no G_IO_FLAG_NONBLOCK */
+       g_return_val_if_fail((flags&G_IO_FLAG_SET_MASK)==0,G_IO_STATUS_ERROR);
+
+       return G_IO_STATUS_NORMAL;
+}
+
+
+static GIOFlags captive_io_channel_io_get_flags(GIOChannel *channel)
+{
+struct captive_io_channel *captive_io_channel=(struct captive_io_channel *)channel;
+
+       g_return_val_if_fail(validate_captive_io_channel(captive_io_channel),0);
+
+       return 0;       /* | !G_IO_FLAG_APPEND | !G_IO_FLAG_NONBLOCK */
+}
+
+
+struct captive_io_channel *captive_io_channel_new(Captive_CaptiveIOChannel corba_captive_io_channel,gboolean writeable)
+{
+struct captive_io_channel *captive_io_channel;
+
+       g_return_val_if_fail(corba_captive_io_channel!=NULL,NULL);
+
+       G_LOCK(captive_io_channel_funcs);
+       captive_io_channel_funcs.io_read        =captive_io_channel_io_read;
+       captive_io_channel_funcs.io_write       =captive_io_channel_io_write;
+       captive_io_channel_funcs.io_seek        =captive_io_channel_io_seek;
+       captive_io_channel_funcs.io_close       =captive_io_channel_io_close;
+       captive_io_channel_funcs.io_create_watch=captive_io_channel_io_create_watch;
+       captive_io_channel_funcs.io_free        =captive_io_channel_io_free;
+       captive_io_channel_funcs.io_set_flags   =captive_io_channel_io_set_flags;
+       captive_io_channel_funcs.io_get_flags   =captive_io_channel_io_get_flags;
+       G_UNLOCK(captive_io_channel_funcs);
+
+       captive_new(captive_io_channel);
+       g_assert(G_STRUCT_OFFSET(struct captive_io_channel,iochannel)==0);      /* safely re-type-able */
+       g_io_channel_init(&captive_io_channel->iochannel);
+       captive_io_channel->iochannel.funcs=&captive_io_channel_funcs;
+       captive_io_channel->iochannel.is_seekable=TRUE;
+       captive_io_channel->iochannel.is_readable=TRUE;
+       captive_io_channel->iochannel.is_writeable=writeable;
+       captive_io_channel->iochannel.close_on_unref=TRUE;      /* run g_io_channel_shutdown() flush on last unref */
+       captive_io_channel->corba_captive_io_channel=corba_captive_io_channel;
+
+       return captive_io_channel;
+}
+
+
+gboolean captive_io_channel_get_size(GIOChannel *giochannel,guint64 *size_return)
+{
+struct captive_io_channel *captive_io_channel;
+
+       g_return_val_if_fail(giochannel!=NULL,FALSE);
+       g_return_val_if_fail(size_return!=NULL,FALSE);
+
+       if (giochannel->funcs!=&captive_io_channel_funcs)
+               return FALSE;
+       captive_io_channel=(struct captive_io_channel *)giochannel;
+
+       *size_return=Captive_CaptiveIOChannel_size(captive_io_channel->corba_captive_io_channel,&captive_corba_ev);
+       if (GNOME_VFS_OK!=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev))
+               return FALSE;
+
+       return TRUE;
+}
diff --git a/src/libcaptive/sandbox/client-CaptiveIOChannel.h b/src/libcaptive/sandbox/client-CaptiveIOChannel.h
new file mode 100644 (file)
index 0000000..63bb026
--- /dev/null
@@ -0,0 +1,40 @@
+/* $Id$
+ * Include file for CORBA/ORBit client side of image GIOChannel object of sandbox_child()
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _CLIENT_CAPTIVEIOCHANNEL_H
+#define _CLIENT_CAPTIVEIOCHANNEL_H 1
+
+
+#include <glib/gmacros.h>
+#ifdef ORBIT2  /* Prevent missing $(ORBIT_CFLAGS) outside of libcaptive/sandbox/ */
+#include "sandbox.h"
+#endif
+
+
+G_BEGIN_DECLS
+
+#ifdef ORBIT2  /* Prevent missing $(ORBIT_CFLAGS) outside of libcaptive/sandbox/ */
+struct captive_io_channel *captive_io_channel_new(Captive_CaptiveIOChannel corba_captive_io_channel,gboolean writeable);
+#endif
+gboolean captive_io_channel_get_size(GIOChannel *giochannel,guint64 *size_return);
+
+G_END_DECLS
+
+
+#endif /* _CLIENT_CAPTIVEIOCHANNEL_H */
diff --git a/src/libcaptive/sandbox/server-CaptiveIOChannel.c b/src/libcaptive/sandbox/server-CaptiveIOChannel.c
new file mode 100644 (file)
index 0000000..db71790
--- /dev/null
@@ -0,0 +1,178 @@
+/* $Id$
+ * CORBA/ORBit client side of image GIOChannel object of sandbox_child()
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "config.h"
+
+#include "server-CaptiveIOChannel.h"   /* self */
+#include "sandbox.h"
+#include <glib/gmessages.h>
+#include "captive/macros.h"
+#include "split.h"
+#include <libgnomevfs/gnome-vfs-file-size.h>
+#include "captive/storage.h"
+
+
+static void impl_Captive_CaptiveIOChannel_fini(impl_POA_Captive_CaptiveIOChannel *servant,CORBA_Environment *ev);
+static void impl_Captive_CaptiveIOChannel_read(impl_POA_Captive_CaptiveIOChannel *servant,
+               Captive_Bytes **buffer_corba_return,const Captive_GSize count,CORBA_Environment *ev);
+static void impl_Captive_CaptiveIOChannel_write(impl_POA_Captive_CaptiveIOChannel *servant,
+               const Captive_Bytes *buffer,Captive_GSize *bytes_written_return,CORBA_Environment *ev);
+static void impl_Captive_CaptiveIOChannel_seek
+               (impl_POA_Captive_CaptiveIOChannel *servant,const Captive_GInt64 offset,const Captive_GSeekType type,CORBA_Environment *ev);
+static Captive_GUInt64 impl_Captive_CaptiveIOChannel_size(impl_POA_Captive_CaptiveIOChannel *servant,CORBA_Environment *ev);
+
+
+static PortableServer_ServantBase__epv impl_Captive_CaptiveIOChannel_base_epv={
+       NULL,   /* _private data */
+       (gpointer)&impl_Captive_CaptiveIOChannel_fini,  /* finalize routine */
+       NULL,   /* default_POA routine */
+       };
+static POA_Captive_CaptiveIOChannel__epv impl_Captive_CaptiveIOChannel_epv={
+       NULL,   /* _private */
+       (gpointer)&impl_Captive_CaptiveIOChannel_read,
+       (gpointer)&impl_Captive_CaptiveIOChannel_write,
+       (gpointer)&impl_Captive_CaptiveIOChannel_seek,
+       (gpointer)&impl_Captive_CaptiveIOChannel_size,
+       };
+static POA_Captive_CaptiveIOChannel__vepv impl_Captive_CaptiveIOChannel_vepv={
+       &impl_Captive_CaptiveIOChannel_base_epv,
+       &impl_Captive_CaptiveIOChannel_epv,
+       };
+
+
+Captive_CaptiveIOChannel impl_Captive_CaptiveIOChannel__create
+               (PortableServer_POA poa,GIOChannel *image_iochannel,CORBA_Environment *ev)
+{
+Captive_CaptiveIOChannel retval;
+impl_POA_Captive_CaptiveIOChannel *newservant;
+PortableServer_ObjectId *objid;
+GIOStatus erriostatus;
+
+       captive_new0(newservant);       /* FIXME: leak */
+       newservant->servant.vepv=&impl_Captive_CaptiveIOChannel_vepv;
+       newservant->poa=poa;
+
+       newservant->image_iochannel=image_iochannel;
+       erriostatus=g_io_channel_set_encoding(newservant->image_iochannel,
+                       NULL, /* encoding; force binary data */
+                       NULL);  /* error */
+       g_assert(erriostatus==G_IO_STATUS_NORMAL);
+
+       /* captive_giochannel_size() only _after_ g_io_channel_set_encoding() ! */
+       newservant->image_size=captive_giochannel_size(newservant->image_iochannel);
+       g_return_val_if_fail(newservant->image_size>0,NULL);
+
+       POA_Captive_CaptiveIOChannel__init((PortableServer_Servant)newservant,ev);
+       objid=PortableServer_POA_activate_object(poa,newservant,ev);
+       CORBA_free(objid);
+       retval=PortableServer_POA_servant_to_reference(poa,newservant,ev);
+
+       return retval;
+}
+
+
+static void impl_Captive_CaptiveIOChannel_fini(impl_POA_Captive_CaptiveIOChannel *servant,CORBA_Environment *ev)
+{
+       /* FIXME: Any flushes? */
+}
+
+
+void impl_Captive_CaptiveIOChannel__destroy(impl_POA_Captive_CaptiveIOChannel *servant,CORBA_Environment *ev)
+{
+PortableServer_ObjectId *objid;
+
+       objid=PortableServer_POA_servant_to_id(servant->poa,servant,ev);
+       PortableServer_POA_deactivate_object(servant->poa,objid,ev);
+       CORBA_free(objid);
+       impl_Captive_CaptiveIOChannel_fini(servant,ev);
+       g_free(servant);
+}
+
+
+static void impl_Captive_CaptiveIOChannel_read(impl_POA_Captive_CaptiveIOChannel *servant,
+               Captive_Bytes **buffer_corba_return,const Captive_GSize count,CORBA_Environment *ev)
+{
+Captive_Bytes *buffer_corba;
+gsize bytes_read;
+GIOStatus erriostatus;
+
+       buffer_corba=Captive_Bytes__alloc();
+       buffer_corba->_maximum=count;
+       buffer_corba->_length=0;
+       buffer_corba->_buffer=Captive_Bytes_allocbuf(buffer_corba->_maximum);
+       buffer_corba->_release=TRUE;
+
+       erriostatus=g_io_channel_read_chars(servant->image_iochannel,
+                       buffer_corba->_buffer,  /* buf */
+                       count,  /* count */
+                       &bytes_read,    /* bytes_read */
+                       NULL);  /* error */
+       if (erriostatus==G_IO_STATUS_EOF) {
+               g_assert(bytes_read==0);
+               bytes_read=0;
+               erriostatus=G_IO_STATUS_NORMAL;
+               }
+       if (erriostatus!=G_IO_STATUS_NORMAL) {
+               captive_sandbox_child_GnomeVFSResultException_throw(ev,GNOME_VFS_ERROR_IO);
+               Captive_Bytes__freekids(buffer_corba,NULL/* 'd'; meaning? */);
+               CORBA_free(buffer_corba);
+               return;
+               }
+
+       buffer_corba->_length=bytes_read;
+       *buffer_corba_return=buffer_corba;
+}
+
+
+static void impl_Captive_CaptiveIOChannel_write(impl_POA_Captive_CaptiveIOChannel *servant,
+               const Captive_Bytes *buffer_corba,Captive_GSize *bytes_written_return,CORBA_Environment *ev)
+{
+gsize bytes_written;
+
+       if (G_IO_STATUS_NORMAL!=g_io_channel_write_chars(servant->image_iochannel,
+                       buffer_corba->_buffer,  /* buf */
+                       buffer_corba->_length,  /* count */
+                       &bytes_written, /* bytes_written */
+                       NULL)   /* error */
+                                       || bytes_written!=buffer_corba->_length) {
+               captive_sandbox_child_GnomeVFSResultException_throw(ev,GNOME_VFS_ERROR_IO);
+               return;
+               }
+
+       *bytes_written_return=bytes_written;
+}
+
+
+static void impl_Captive_CaptiveIOChannel_seek
+               (impl_POA_Captive_CaptiveIOChannel *servant,const Captive_GInt64 offset,const Captive_GSeekType type,CORBA_Environment *ev)
+{
+       if (G_IO_STATUS_NORMAL!=g_io_channel_seek_position(servant->image_iochannel,
+                       offset, /* offset */
+                       type,   /* type */
+                       NULL)) {        /* error */
+               captive_sandbox_child_GnomeVFSResultException_throw(ev,GNOME_VFS_ERROR_IO);
+               return;
+               }
+}
+
+
+static Captive_GUInt64 impl_Captive_CaptiveIOChannel_size(impl_POA_Captive_CaptiveIOChannel *servant,CORBA_Environment *ev)
+{
+       return servant->image_size;
+}
diff --git a/src/libcaptive/sandbox/server-CaptiveIOChannel.h b/src/libcaptive/sandbox/server-CaptiveIOChannel.h
new file mode 100644 (file)
index 0000000..8efbc0a
--- /dev/null
@@ -0,0 +1,45 @@
+/* $Id$
+ * Include file for CORBA/ORBit client side of image GIOChannel object of sandbox_child()
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _SERVER_CAPTIVEIOCHANNEL_H
+#define _SERVER_CAPTIVEIOCHANNEL_H 1
+
+
+#include <glib/gmacros.h>
+#include "sandbox.h"
+
+
+G_BEGIN_DECLS
+
+typedef struct {
+       POA_Captive_CaptiveIOChannel servant;
+       PortableServer_POA poa;
+       GIOChannel *image_iochannel;
+       guint64 image_size;
+       } impl_POA_Captive_CaptiveIOChannel;
+
+
+Captive_CaptiveIOChannel impl_Captive_CaptiveIOChannel__create
+               (PortableServer_POA poa,GIOChannel *image_iochannel,CORBA_Environment *ev);
+void impl_Captive_CaptiveIOChannel__destroy(impl_POA_Captive_CaptiveIOChannel *servant,CORBA_Environment *ev);
+
+G_END_DECLS
+
+
+#endif /* _SERVER_CAPTIVEIOCHANNEL_H */
index f1a80c2..7dfbbe7 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "captive/storage.h"   /* self */
 #include "../client/giochannel-blind.h"        /* for captive_giochannel_blind_get_size() */
+#include "../sandbox/client-CaptiveIOChannel.h"        /* for captive_io_channel_get_size() */
 #include <glib/gmessages.h>
 #include <glib/gtypes.h>
 #include <fcntl.h>
@@ -46,6 +47,19 @@ guint64 r;
 }
 
 
+static guint64 size_sandbox(GIOChannel *iochannel)
+{
+guint64 r;
+
+       g_return_val_if_fail(iochannel!=NULL,0);
+
+       if (!captive_io_channel_get_size(iochannel,&r))
+               return 0;
+
+       return r;
+}
+
+
 static GIOChannel *iochannel_null;
 
 static int iounixchannel_get_fd(GIOChannel *iochannel)
@@ -197,6 +211,8 @@ guint64 r;
 
        if ((r=size_blind(iochannel)))
                return r;
+       if ((r=size_sandbox(iochannel)))
+               return r;
        if ((r=size_ioctl(iochannel)))
                return r;
        if ((r=size_seek(iochannel)))