+captive-bug-replay client to read --bug-pathname bugreports.
authorshort <>
Fri, 18 Jul 2003 11:29:57 +0000 (11:29 +0000)
committershort <>
Fri, 18 Jul 2003 11:29:57 +0000 (11:29 +0000)
autogen.pl
configure.in
src/client/Makefile.am
src/client/bug-replay/Makefile.am [new file with mode: 0644]
src/client/bug-replay/main.c [new file with mode: 0644]

index 6079237..5bca278 100755 (executable)
@@ -41,6 +41,7 @@ AutoGen->run(
                                ./ChangeLog.bak
                                ./doc/*-pod.*
                                ./doc/apiref/captive.types
+                               ./src/client/bug-replay/captive-bug-replay
                                ./src/client/cmdline/captive-cmdline
                                ./src/client/sandbox-server/captive-sandbox-server
                                ./src/client/libcaptive-gnomevfs/captive.conf
index d6dc64f..294a0e8 100644 (file)
@@ -267,9 +267,10 @@ Makefile
 ./src/libcaptive/sandbox/Makefile
 ./src/libcaptive/client/Makefile
 ./src/client/Makefile
+./src/client/bug-replay/Makefile
 ./src/client/cmdline/Makefile
-./src/client/sandbox-server/Makefile
 ./src/client/libcaptive-gnomevfs/Makefile
+./src/client/sandbox-server/Makefile
 ./doc/Makefile
 ./doc/apiref/Makefile
 ./src/client/libcaptive-gnomevfs/captive.conf
index b2e1bf1..c0757b6 100644 (file)
@@ -18,4 +18,4 @@
 
 include $(top_srcdir)/Makefile-head.am
 
-SUBDIRS=cmdline sandbox-server libcaptive-gnomevfs
+SUBDIRS=cmdline sandbox-server libcaptive-gnomevfs bug-replay
diff --git a/src/client/bug-replay/Makefile.am b/src/client/bug-replay/Makefile.am
new file mode 100644 (file)
index 0000000..e46c399
--- /dev/null
@@ -0,0 +1,25 @@
+# $Id$
+# automake source for developer replaying of bugreport snapshots
+# 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 $(top_srcdir)/Makefile-head.am
+
+captive_bug_replay_SOURCES= \
+               main.c
+captive_bug_replay_CFLAGS=                   $(LIBXML_CFLAGS) $(GNOME_VFS_MODULE_CFLAGS)
+captive_bug_replay_LDADD =$(captive_library) $(LIBXML_LIBS)
+bin_PROGRAMS+=captive-bug-replay
diff --git a/src/client/bug-replay/main.c b/src/client/bug-replay/main.c
new file mode 100644 (file)
index 0000000..59615ed
--- /dev/null
@@ -0,0 +1,530 @@
+/* $Id$
+ * developer replaying of bugreport snapshots
+ * 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 <glib/gmessages.h>
+#include <stdlib.h>
+#include <glib/giochannel.h>
+#include <popt.h>
+#include <string.h>
+#include <stdio.h>
+#include <libxml/xmlreader.h>
+#include <glib-object.h>       /* for g_type_init() */
+#include <glib/ghash.h>
+
+#include <captive/libxml.h>
+#include <captive/options.h>
+#include <captive/macros.h>
+#include "../../libcaptive/client/giochannel-blind.h"  /* FIXME: pathname */
+#include <captive/client-vfs.h>
+#include <captive/client-directory.h>
+#include <captive/client-file.h>
+
+
+static gchar *optarg_module_path;
+
+static const struct poptOption popt_table[]={
+#define BUG_REPLAY_POPT(longname,argInfoP,argP,descripP,argDescripP) \
+               { \
+                       longName: (longname), \
+                       shortName: 0, \
+                       argInfo: (argInfoP), \
+                       arg: (void *)argP, \
+                       val: 0, \
+                       descrip: (descripP), \
+                       argDescrip: (argDescripP), \
+               }
+
+               BUG_REPLAY_POPT("module-path",POPT_ARG_STRING,&optarg_module_path,N_("Disk path for W32 modules and filesystem"),N_("path")),
+
+#undef BUG_REPLAY_POPT
+               POPT_AUTOHELP
+               POPT_TABLEEND
+               };
+
+
+static void object_hash_key_destroy_func(const xmlChar *xml_object)
+{
+       g_return_if_fail(xml_object!=NULL);
+
+       xmlFree((xmlChar *)xml_object);
+}
+
+static void object_hash_value_destroy_func(GObject *captive_any_object)
+{
+       g_return_if_fail(G_IS_OBJECT(captive_any_object));
+
+       g_object_unref(captive_any_object);
+}
+
+
+int main(int argc,char **argv)
+{
+poptContext context;
+int errint;
+const char **cmd_argv;
+struct captive_options options;
+xmlTextReader *xml_reader;
+GList *action_list;    /* of 'xmlNode *' */
+gboolean preread;
+gboolean module_is_filesystem=FALSE;
+CaptiveVfsObject *captive_vfs_object;
+gboolean action_is_first;
+xmlNode *xml_node;
+GHashTable *object_hash;
+GObject *object;
+gboolean errbool;
+CaptiveDirectoryObject *captive_directory_object;
+CaptiveFileObject *captive_file_object;
+GnomeVFSResult errgnomevfsresult;
+struct captive_libxml_string_drop_stack *drop_stack=NULL;
+const xmlChar *xml_object;
+
+       /* Prevent output block buffering if redirecting stdout to file. */
+       setvbuf(stdout,(char *)NULL,_IONBF,0);
+       setvbuf(stderr,(char *)NULL,_IONBF,0);
+
+       /* Initialize GObject subsystem of GLib. */
+       g_type_init();
+
+       captive_options_init(&options);
+
+       context=poptGetContext(
+                       PACKAGE,        /* name */
+                       argc,(/*en-const*/const char **)argv,   /* argc,argv */
+                       popt_table,     /* options */
+                       POPT_CONTEXT_POSIXMEHARDER);    /* flags; && !POPT_CONTEXT_KEEP_FIRST */
+       if (context==NULL) {
+               g_assert_not_reached(); /* argument recognization args_error */
+               return EXIT_FAILURE;
+               }
+       errint=poptReadDefaultConfig(context,
+                       TRUE);  /* useEnv */
+       if (errint!=0) {
+               g_assert_not_reached(); /* argument recognization args_error */
+               return EXIT_FAILURE;
+               }
+       errint=poptGetNextOpt(context);
+       if (errint!=-1) {
+               g_assert_not_reached(); /* some non-callbacked argument reached */
+               return EXIT_FAILURE;
+               }
+       cmd_argv=poptGetArgs(context);
+
+       if (!cmd_argv || !cmd_argv[0] || cmd_argv[1]) {
+               g_error("Exactly one argument required - pathname to .captivebug.xml.gz bugreport to replay");
+               return EXIT_FAILURE;
+               }
+
+  options.rwmode=CAPTIVE_OPTION_RWMODE_BLIND;
+  options.debug_messages=TRUE;
+
+       options.image_iochannel=NULL;
+       action_list=NULL;
+       options.media=CAPTIVE_OPTION_MEDIA_UNKNOWN;
+
+       xml_reader=xmlNewTextReaderFilename(cmd_argv[0]);
+       g_assert(xml_reader!=NULL);
+       preread=FALSE;
+       while (preread || 1==xmlTextReaderRead(xml_reader)) {
+               preread=FALSE;
+               switch (xmlTextReaderNodeType(xml_reader)) {
+
+                       case CAPTIVE_XML_TEXT_READER_NODE_TYPE_COMMENT:
+                               break;
+
+                       case CAPTIVE_XML_TEXT_READER_NODE_TYPE_TEXT:    /* Even empty nodes have some '#text'. */
+                               break;
+
+                       case CAPTIVE_XML_TEXT_READER_NODE_TYPE_END:     /* We do not track tag ends. */
+                               break;
+
+                       case CAPTIVE_XML_TEXT_READER_NODE_TYPE_START: {
+const xmlChar *xml_name;
+
+                               xml_name=xmlTextReaderName(xml_reader);
+                               /**/ if (!xmlStrcmp(xml_name,"bug")) {  /* root tag */
+                                       }
+                               else if (!xmlStrcmp(xml_name,"captive")) {
+const xmlChar *xml_captive_version;
+
+                                       xml_captive_version=captive_libxml_string_drop(&drop_stack,xmlTextReaderGetAttribute(xml_reader,"version"));
+                                       g_assert(xml_captive_version!=NULL);
+                                       g_assert(!xmlStrcmp(xml_captive_version,VERSION));
+                                       }
+                               else if (!xmlStrcmp(xml_name,"filesystem")) {   /* contains <module/> */
+                                       module_is_filesystem=TRUE;
+                                       }
+                               else if (!xmlStrcmp(xml_name,"load_module")) {  /* contains <module/> */
+                                       module_is_filesystem=FALSE;
+                                       }
+                               else if (!xmlStrcmp(xml_name,"module")) {
+const xmlChar *xml_module_basename;
+struct captive_options_module *options_module;
+gboolean errbool;
+
+                                       if (module_is_filesystem)
+                                               options_module=&options.filesystem;
+                                       else {
+                                               captive_new(options_module);
+                                               options.load_module=g_list_append(options.load_module,options_module);
+                                               }
+                                       xml_module_basename=captive_libxml_string_drop(&drop_stack,xmlTextReaderGetAttribute(xml_reader,"basename"));
+                                       g_assert(xml_module_basename!=NULL);
+                                       g_assert(strchr(xml_module_basename,'/')==NULL);        /* a bit of security */
+                                       errbool=captive_options_module_load(options_module,
+                                                       captive_printf_alloca("%s/%s",
+                                                                       (optarg_module_path ? optarg_module_path : "."),xml_module_basename));
+                                       g_assert(errbool==TRUE);
+                                       switch (options_module->type) {
+                                               case CAPTIVE_OPTIONS_MODULE_TYPE_PE32: {
+const xmlChar *xml_module_md5,*xml_module_length;
+
+                                                       if (options_module->u.pe32.md5
+                                                                       && (xml_module_md5=captive_libxml_string_drop(&drop_stack,xmlTextReaderGetAttribute(xml_reader,"version"))))
+                                                               g_assert(!xmlStrcmp(xml_module_md5,options_module->u.pe32.md5));
+                                                       if ((xml_module_length=captive_libxml_string_drop(&drop_stack,xmlTextReaderGetAttribute(xml_reader,"length"))))
+                                                               g_assert(!xmlStrcmp(xml_module_length,
+                                                                               captive_printf_alloca("%lu",(unsigned long)options_module->u.pe32.length)));
+                                                       } break;
+                                               case CAPTIVE_OPTIONS_MODULE_TYPE_GMODULE:
+                                                       /* No possibility to check anything. */
+                                                       break;
+                                               default: g_assert_not_reached();
+                                               }
+                                       }
+                               else if (!xmlStrcmp(xml_name,"action")) {
+int xml_action_depth;
+gboolean action_done,action_preread;
+
+                                       g_assert(action_list==NULL);
+                                       xml_action_depth=xmlTextReaderDepth(xml_reader);
+                                       action_preread=FALSE;
+                                       action_done=FALSE;
+                                       while (!action_done) {
+                                               if (!action_preread) {
+                                                       errint=xmlTextReaderRead(xml_reader);
+                                                       g_assert(errint==1);
+                                                       }
+                                               action_preread=FALSE;
+                                               g_assert(xml_action_depth<=xmlTextReaderDepth(xml_reader));
+                                               switch (xmlTextReaderNodeType(xml_reader)) {
+                                                       case CAPTIVE_XML_TEXT_READER_NODE_TYPE_COMMENT:
+                                                               break;
+                                                       case CAPTIVE_XML_TEXT_READER_NODE_TYPE_TEXT:    /* Even empty nodes have some '#text'. */
+                                                               break;
+                                                       case CAPTIVE_XML_TEXT_READER_NODE_TYPE_END: {   /* We do not track tag ends. */
+                                                               if ((action_done=(xml_action_depth==xmlTextReaderDepth(xml_reader)))) {
+const xmlChar *xml_name_end;
+
+                                                                       xml_name_end=captive_libxml_string_drop(&drop_stack,xmlTextReaderName(xml_reader));
+                                                                       g_assert(!xmlStrcmp(xml_name_end,"action"));
+                                                                       }
+                                                               } break;
+                                                       case CAPTIVE_XML_TEXT_READER_NODE_TYPE_START: {
+xmlNode *xml_node;
+                                                               
+                                                               xml_node=xmlTextReaderExpand(xml_reader);
+                                                               g_assert(xml_node!=NULL);
+                                                               xml_node=xmlCopyNode(xml_node,
+                                                                               1);     /* recursive */
+                                                               errint=xmlTextReaderNext(xml_reader);
+                                                               g_assert(errint==1);
+                                                               action_preread=TRUE;
+                                                               action_list=g_list_prepend(action_list,xml_node);       /* we are prepending to be effective */
+                                                               } break;
+                                                       default: g_assert_not_reached();
+                                                       }
+                                               }
+                                       }
+                               else if (!xmlStrcmp(xml_name,"media")) {
+const xmlChar *xml_media_end_name,*xml_media_type;
+
+                                       g_assert(options.image_iochannel==NULL);
+                                       options.image_iochannel=(GIOChannel *)captive_giochannel_blind_new_from_xml(xml_reader);
+                                       g_assert(CAPTIVE_XML_TEXT_READER_NODE_TYPE_END==xmlTextReaderNodeType(xml_reader));
+                                       xml_media_end_name=xmlTextReaderName(xml_reader);
+                                       g_assert(xml_media_end_name!=NULL);
+                                       g_assert(!xmlStrcmp(xml_media_end_name,"media"));
+                                       xmlFree((xmlChar *)xml_media_end_name);
+                                       xml_media_type=xmlTextReaderGetAttribute(xml_reader,"type");
+                                       g_assert(xml_media_type!=NULL);
+                                       /**/ if (!xmlStrcmp(xml_media_type,"cdrom"))
+                                               options.media=CAPTIVE_OPTION_MEDIA_CDROM;
+                                       else if (!xmlStrcmp(xml_media_type,"disk"))
+                                               options.media=CAPTIVE_OPTION_MEDIA_DISK;
+                                       else g_assert_not_reached();
+                                       xmlFree((xmlChar *)xml_media_type);
+                                       }
+                               else if (!xmlStrcmp(xml_name,"log")) {
+                                       errint=xmlTextReaderNext(xml_reader);
+                                       g_assert(errint==1);
+                                       preread=TRUE;
+                                       }
+                               else g_error("Unknown START node: %s",xml_name);
+                               xmlFree((xmlChar *)xml_name);
+                               } break;
+
+                       default: g_assert_not_reached();
+                       }
+               captive_libxml_string_drop_flush(&drop_stack);
+               }
+       xmlFreeTextReader(xml_reader);
+
+       g_assert(options.image_iochannel!=NULL);
+       action_list=g_list_reverse(action_list);        /* we were g_list_prepend()ing for effectivity */
+       g_assert(options.media!=CAPTIVE_OPTION_MEDIA_UNKNOWN);
+
+       if (GNOME_VFS_OK!=captive_vfs_new(&captive_vfs_object,&options)) {
+               g_error(_("captive_vfs_new() failed"));
+               return EXIT_FAILURE;
+               }
+       captive_options_free(&options);
+
+       /* 'cmd_argv' gets cleared by 'poptFreeContext(context);' below */
+       poptFreeContext(context);
+
+  object_hash=g_hash_table_new_full(
+                       g_str_hash,     /* hash_func */
+                       g_str_equal,    /* key_equal_func */
+                       (GDestroyNotify)object_hash_key_destroy_func,   /* key_destroy_func */
+                       (GDestroyNotify)object_hash_value_destroy_func);        /* value_destroy_func */
+
+       for (
+                       action_is_first=TRUE;
+                       action_list;
+                       xmlFreeNode(xml_node),action_is_first=FALSE) {
+
+               captive_libxml_string_drop_flush(&drop_stack);
+
+#define GET_PROP_STRING(prop_name) ({ \
+               const xmlChar *_get_prop_string_r=captive_libxml_string_drop(&drop_stack,xmlGetProp(xml_node,(prop_name))); \
+               g_assert(_get_prop_string_r!=NULL); \
+               _get_prop_string_r; \
+               })
+#define GET_PROP_GINT64(prop_name) (captive_libxml_sscanf_gint64(GET_PROP_STRING((prop_name))))
+
+               xml_node=action_list->data;
+               g_assert(xml_node!=NULL);
+               action_list=g_list_delete_link(action_list,action_list);
+               g_message("replay action: %s()",xml_node->name);
+               xml_object=GET_PROP_STRING("object");
+               object=g_hash_table_lookup(object_hash,xml_object);
+               g_assert(object==NULL || G_IS_OBJECT(object));
+
+               if (!xmlStrcmp(xml_node->name,"vfs_new")) {
+                       g_assert(action_is_first==TRUE);
+                       g_assert(captive_vfs_object!=NULL);
+                       g_assert(object==NULL);
+                       g_hash_table_insert(object_hash,g_strdup(xml_object),captive_vfs_object);
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"vfs_commit")) {
+                       g_assert(action_is_first==TRUE);
+                       g_assert(captive_vfs_object!=NULL);
+                       g_assert(object==NULL);
+                       g_hash_table_insert(object_hash,g_strdup(xml_object),captive_vfs_object);
+                       continue;
+                       }
+               g_assert(action_is_first==FALSE);
+               if (!xmlStrcmp(xml_node->name,"vfs_close")) {
+                       g_assert(captive_vfs_object!=NULL);
+                       g_assert(CAPTIVE_VFS_OBJECT(object)==captive_vfs_object);
+                       errbool=g_hash_table_remove(object_hash,xml_object);    /* g_object_unref() by object_hash_value_destroy_func() */
+                       g_assert(errbool==TRUE);
+                       continue;
+                       }
+               g_assert(captive_vfs_object!=NULL);
+
+               /* DIRECTORY */
+               if (!xmlStrcmp(xml_node->name,"directory_new_open")) {
+                       g_assert(object==NULL);
+                       errgnomevfsresult=captive_directory_new_open(&captive_directory_object,captive_vfs_object,
+                                       GET_PROP_STRING("pathname"));
+                       g_assert((errgnomevfsresult==GNOME_VFS_OK)==GET_PROP_GINT64("result"));
+                       if (errgnomevfsresult==GNOME_VFS_OK)
+                               g_hash_table_insert(object_hash,g_strdup(xml_object),captive_directory_object);
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"directory_new_make")) {
+                       g_assert(object==NULL);
+                       errgnomevfsresult=captive_directory_new_make(&captive_directory_object,captive_vfs_object,
+                                       GET_PROP_STRING("pathname"),
+                                       GET_PROP_GINT64("perm"));
+                       g_assert((errgnomevfsresult==GNOME_VFS_OK)==GET_PROP_GINT64("result"));
+                       if (errgnomevfsresult==GNOME_VFS_OK)
+                               g_hash_table_insert(object_hash,g_strdup(xml_object),captive_directory_object);
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"directory_close")) {
+                       captive_directory_object=CAPTIVE_DIRECTORY_OBJECT(object);
+                       errbool=g_hash_table_remove(object_hash,xml_object);    /* g_object_unref() by object_hash_value_destroy_func() */
+                       g_assert(errbool==TRUE);
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"directory_read")) {
+GnomeVFSFileInfo file_info;
+
+                       captive_directory_object=CAPTIVE_DIRECTORY_OBJECT(object);
+                       errgnomevfsresult=captive_directory_read(captive_directory_object,&file_info);
+                       g_assert(!strcmp(gnome_vfs_result_to_string(errgnomevfsresult),GET_PROP_STRING("result")));
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"directory_remove")) {
+                       captive_directory_object=CAPTIVE_DIRECTORY_OBJECT(object);
+                       errgnomevfsresult=captive_directory_remove(captive_directory_object);
+                       g_assert(!strcmp(gnome_vfs_result_to_string(errgnomevfsresult),GET_PROP_STRING("result")));
+                       continue;
+                       }
+
+               /* FILE */
+               if (!xmlStrcmp(xml_node->name,"file_new_open")) {
+                       g_assert(object==NULL);
+                       errgnomevfsresult=captive_file_new_open(&captive_file_object,captive_vfs_object,
+                                       GET_PROP_STRING("pathname"),
+                                       GET_PROP_GINT64("mode"));
+                       g_assert((errgnomevfsresult==GNOME_VFS_OK)==GET_PROP_GINT64("result"));
+                       if (errgnomevfsresult==GNOME_VFS_OK)
+                               g_hash_table_insert(object_hash,g_strdup(xml_object),captive_file_object);
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"file_new_create")) {
+                       g_assert(object==NULL);
+                       errgnomevfsresult=captive_file_new_create(&captive_file_object,captive_vfs_object,
+                                       GET_PROP_STRING("pathname"),
+                                       GET_PROP_GINT64("mode"),
+                                       GET_PROP_GINT64("exclusive"),
+                                       GET_PROP_GINT64("perm"));
+                       g_assert((errgnomevfsresult==GNOME_VFS_OK)==GET_PROP_GINT64("result"));
+                       if (errgnomevfsresult==GNOME_VFS_OK)
+                               g_hash_table_insert(object_hash,g_strdup(xml_object),captive_file_object);
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"file_close")) {
+                       captive_file_object=CAPTIVE_FILE_OBJECT(object);
+                       errbool=g_hash_table_remove(object_hash,xml_object);    /* g_object_unref() by object_hash_value_destroy_func() */
+                       g_assert(errbool==TRUE);
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"file_read")) {
+gpointer buffer;
+GnomeVFSFileSize num_bytes,bytes_read;
+
+                       captive_file_object=CAPTIVE_FILE_OBJECT(object);
+                       num_bytes=GET_PROP_GINT64("num_bytes");
+                       buffer=g_malloc(num_bytes);
+                       errgnomevfsresult=captive_file_read(captive_file_object,buffer,num_bytes,&bytes_read);
+                       g_assert(!strcmp(gnome_vfs_result_to_string(errgnomevfsresult),GET_PROP_STRING("result")));
+                       if (errgnomevfsresult==GNOME_VFS_OK)
+                               g_assert((gint64)bytes_read==GET_PROP_GINT64("bytes_read_return"));
+                       g_free(buffer);
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"file_write")) {
+gpointer buffer;
+GnomeVFSFileSize num_bytes,bytes_written;
+
+                       captive_file_object=CAPTIVE_FILE_OBJECT(object);
+                       num_bytes=GET_PROP_GINT64("num_bytes");
+                       buffer=g_malloc(num_bytes);
+                       memset(buffer,'X',num_bytes);   /* FIXME: better pattern */
+                       errgnomevfsresult=captive_file_write(captive_file_object,buffer,num_bytes,&bytes_written);
+                       g_assert(!strcmp(gnome_vfs_result_to_string(errgnomevfsresult),GET_PROP_STRING("result")));
+                       if (errgnomevfsresult==GNOME_VFS_OK)
+                               g_assert((gint64)bytes_written==GET_PROP_GINT64("bytes_written_return"));
+                       g_free(buffer);
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"file_seek")) {
+GnomeVFSSeekPosition whence;
+const xmlChar *whence_string;
+
+                       captive_file_object=CAPTIVE_FILE_OBJECT(object);
+                       whence_string=GET_PROP_STRING("whence");
+                       /**/ if (!xmlStrcmp(whence_string,"start"  )) whence=GNOME_VFS_SEEK_START;
+                       else if (!xmlStrcmp(whence_string,"current")) whence=GNOME_VFS_SEEK_CURRENT;
+                       else if (!xmlStrcmp(whence_string,"end"    )) whence=GNOME_VFS_SEEK_END;
+                       else g_assert_not_reached();
+                       errgnomevfsresult=captive_file_seek(captive_file_object,whence,
+                                       GET_PROP_GINT64("offset"));
+                       g_assert(!strcmp(gnome_vfs_result_to_string(errgnomevfsresult),GET_PROP_STRING("result")));
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"file_tell")) {
+GnomeVFSFileOffset offset;
+
+                       captive_file_object=CAPTIVE_FILE_OBJECT(object);
+                       errgnomevfsresult=captive_file_tell(captive_file_object,&offset);
+                       g_assert(!strcmp(gnome_vfs_result_to_string(errgnomevfsresult),GET_PROP_STRING("result")));
+                       if (errgnomevfsresult==GNOME_VFS_OK)
+                               g_assert((gint64)offset==GET_PROP_GINT64("offset"));
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"file_remove")) {
+                       captive_file_object=CAPTIVE_FILE_OBJECT(object);
+                       errgnomevfsresult=captive_file_remove(captive_file_object);
+                       g_assert(!strcmp(gnome_vfs_result_to_string(errgnomevfsresult),GET_PROP_STRING("result")));
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"file_file_info_get")) {
+GnomeVFSFileInfo file_info;
+
+                       captive_file_object=CAPTIVE_FILE_OBJECT(object);
+                       errgnomevfsresult=captive_file_file_info_get(captive_file_object,&file_info);
+                       g_assert(!strcmp(gnome_vfs_result_to_string(errgnomevfsresult),GET_PROP_STRING("result")));
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"file_file_info_set")) {
+GnomeVFSFileInfo file_info;
+
+                       captive_file_object=CAPTIVE_FILE_OBJECT(object);
+                       /* FIXME: We do not have 'file_info' content in the bug file! */
+                       errgnomevfsresult=captive_file_file_info_get(captive_file_object,&file_info);
+                       g_assert(errgnomevfsresult==GNOME_VFS_OK);
+                       errgnomevfsresult=captive_file_file_info_set(captive_file_object,&file_info,
+                                       GET_PROP_GINT64("mask"));
+                       g_assert(!strcmp(gnome_vfs_result_to_string(errgnomevfsresult),GET_PROP_STRING("result")));
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"file_truncate")) {
+                       captive_file_object=CAPTIVE_FILE_OBJECT(object);
+                       errgnomevfsresult=captive_file_truncate(captive_file_object,
+                                       GET_PROP_GINT64("file_size"));
+                       g_assert(!strcmp(gnome_vfs_result_to_string(errgnomevfsresult),GET_PROP_STRING("result")));
+                       continue;
+                       }
+               if (!xmlStrcmp(xml_node->name,"file_move")) {
+                       captive_file_object=CAPTIVE_FILE_OBJECT(object);
+                       errgnomevfsresult=captive_file_move(captive_file_object,
+                                       GET_PROP_STRING("pathname_new"),
+                                       GET_PROP_GINT64("force_replace"));
+                       g_assert(!strcmp(gnome_vfs_result_to_string(errgnomevfsresult),GET_PROP_STRING("result")));
+                       continue;
+                       }
+
+               g_error("Unknown action: %s()",xml_node->name);
+
+#undef GET_PROP_GINT64
+#undef GET_PROP_STRING
+               }
+
+       g_error("All actions were processed, no vfs_close() found");
+       return EXIT_FAILURE;
+}