Implemented sub-second W32 filesystem interface by new: CaptiveFileInfoObject
[captive.git] / src / libcaptive / sandbox / parent-Directory.c
index a21a9d6..ebcaa54 100644 (file)
@@ -1,5 +1,5 @@
 /* $Id$
- * CORBA/ORBit server side of Directory object of sandbox_parent()
+ * CORBA/ORBit client side of Directory object of sandbox_parent()
  * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
  * 
  * This program is free software; you can redistribute it and/or modify
 
 #include "config.h"
 
-#include "captive/parent-Directory.h"  /* self */
+#include "parent-Directory.h"  /* self */
 #include <glib/gmessages.h>
 #include "split.h"
 #include "sandbox.h"
 #include "../client/directory.h"
 #include "../client/vfs.h"
 #include "FileInfo.h"
+#include "captive/macros.h"
+#include "../client/vfs-parent.h"
+#include "captive/client-file-info.h"
 
 
 GnomeVFSResult captive_sandbox_parent_directory_new_open
-               (CaptiveDirectoryObject *captive_directory_object,const gchar *pathname)
+               (CaptiveDirectoryParentObject *captive_directory_parent_object)
 {
-       g_return_val_if_fail(captive_directory_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
-       g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
-       g_return_val_if_fail(captive_directory_object->dir_Handle==NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+xmlNode *xml_action=NULL;
+CaptiveVfsParentObject *captive_vfs_parent_object;
+GnomeVFSResult r;
+Captive_Directory corba_Directory_object;
+
+       g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
+       g_return_val_if_fail(captive_directory_parent_object->pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+
+       captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(CAPTIVE_DIRECTORY_OBJECT(captive_directory_parent_object)->vfs);
 
-       captive_directory_object->corba_Directory_object=Captive_Vfs_directory_new_open(
-                       captive_directory_object->vfs->corba_Vfs_object,pathname,&captive_corba_ev);
+       if (captive_vfs_parent_object->corba_bug_action) {
+               xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "directory_new_open",NULL);
+               xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_directory_parent_object));
+               xmlNewProp(xml_action,BAD_CAST "pathname",BAD_CAST captive_directory_parent_object->pathname);
+               }
 
-       return captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev);
+       corba_Directory_object=Captive_Vfs_directory_new_open(
+                       captive_vfs_parent_object->corba_Vfs_object,captive_directory_parent_object->pathname,&captive_corba_ev);
+       if (xml_action)
+               xmlNewProp(xml_action,BAD_CAST "result",BAD_CAST (captive_corba_ev._major==CORBA_NO_EXCEPTION ? "1" : "0"));
+       /* If 'r' means failure 'corba_Directory_object' may not be 'CORBA_OBJECT_NIL'
+        * although it is not valid 'CORBA_Object' to be passed to CORBA_Object_release().
+        */
+       if (GNOME_VFS_OK!=(r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object)))
+               return r;
+
+       captive_directory_parent_object->corba_Directory_object=corba_Directory_object;
+       return GNOME_VFS_OK;
 }
 
 
 GnomeVFSResult captive_sandbox_parent_directory_new_make
-               (CaptiveDirectoryObject *captive_directory_object,const gchar *pathname,guint perm)
+               (CaptiveDirectoryParentObject *captive_directory_parent_object,guint perm)
 {
-       g_return_val_if_fail(captive_directory_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
-       g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
-       g_return_val_if_fail(captive_directory_object->dir_Handle==NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+xmlNode *xml_action=NULL;
+CaptiveVfsParentObject *captive_vfs_parent_object;
+GnomeVFSResult r;
+Captive_Directory corba_Directory_object;
+
+       g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
+       g_return_val_if_fail(captive_directory_parent_object->pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+
+       captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(CAPTIVE_DIRECTORY_OBJECT(captive_directory_parent_object)->vfs);
 
-       captive_directory_object->corba_Directory_object=Captive_Vfs_directory_new_make(
-                       captive_directory_object->vfs->corba_Vfs_object,pathname,perm,&captive_corba_ev);
+       if (captive_vfs_parent_object->corba_bug_action) {
+               xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "directory_new_make",NULL);
+               xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_directory_parent_object));
+               xmlNewProp(xml_action,BAD_CAST "pathname",BAD_CAST captive_directory_parent_object->pathname);
+               xmlNewProp(xml_action,BAD_CAST "perm",BAD_CAST captive_printf_alloca("%u",(unsigned)perm));
+               }
 
-       return captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev);
+       corba_Directory_object=Captive_Vfs_directory_new_make(
+                       captive_vfs_parent_object->corba_Vfs_object,captive_directory_parent_object->pathname,perm,&captive_corba_ev);
+       if (xml_action)
+               xmlNewProp(xml_action,BAD_CAST "result",BAD_CAST (captive_corba_ev._major==CORBA_NO_EXCEPTION ? "1" : "0"));
+       /* If 'r' means failure 'corba_Directory_object' may not be 'CORBA_OBJECT_NIL'
+        * although it is not valid 'CORBA_Object' to be passed to CORBA_Object_release().
+        */
+       if (GNOME_VFS_OK!=(r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object)))
+               return r;
+
+       captive_directory_parent_object->corba_Directory_object=corba_Directory_object;
+       return GNOME_VFS_OK;
 }
 
 
-GnomeVFSResult captive_sandbox_parent_directory_close(CaptiveDirectoryObject *captive_directory_object)
+GnomeVFSResult captive_sandbox_parent_directory_close(CaptiveDirectoryParentObject *captive_directory_parent_object)
 {
-       g_return_val_if_fail(captive_directory_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
-       g_return_val_if_fail(captive_directory_object->dir_Handle==NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+GnomeVFSResult r;
+xmlNode *xml_action=NULL;
+CaptiveVfsParentObject *captive_vfs_parent_object;
 
-       CORBA_Object_release((CORBA_Object)captive_directory_object->corba_Directory_object,&captive_corba_ev);
-       captive_directory_object->corba_Directory_object=CORBA_OBJECT_NIL;
+       g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
 
-       return captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev);
-}
+       captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(CAPTIVE_DIRECTORY_OBJECT(captive_directory_parent_object)->vfs);
 
+       if (captive_vfs_parent_object->corba_bug_action) {
+               xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "directory_close",NULL);
+               xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_directory_parent_object));
+               }
 
-GnomeVFSResult captive_sandbox_parent_directory_read
-               (CaptiveDirectoryObject *captive_directory_object,GnomeVFSFileInfo *file_info_captive)
+       Captive_Directory_shutdown(captive_directory_parent_object->corba_Directory_object,&captive_corba_ev);
+       r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object);
+       if (xml_action)
+               xmlNewProp(xml_action,BAD_CAST "result",BAD_CAST gnome_vfs_result_to_string(r));
+
+       /* Always clear 'corba_Directory_object' even if 'r' means failure. */
+       CORBA_Object_release((CORBA_Object)captive_directory_parent_object->corba_Directory_object,&captive_corba_ev);
+       captive_directory_parent_object->corba_Directory_object=CORBA_OBJECT_NIL;
+
+       if (captive_directory_parent_object->corba_Directory_file_info_list) {
+GList *file_info_last_l=g_list_last(captive_directory_parent_object->corba_Directory_file_info_list);
+
+               /* Prevent gnome_vfs_file_info_list_free() and its gnome_vfs_file_info_unref()
+                * on the last 'file_info_list' items as it is EOF with NULL '->data'.
+                */
+               /* Do not: g_assert(file_info_last_l->data==NULL);      * directory EOF *
+                * as the crashed client may not produced the trailing NULL.
+                */
+               if (!file_info_last_l->data)
+                       captive_directory_parent_object->corba_Directory_file_info_list=g_list_delete_link(
+                                       captive_directory_parent_object->corba_Directory_file_info_list,file_info_last_l);
+               gnome_vfs_file_info_list_free(captive_directory_parent_object->corba_Directory_file_info_list);
+               captive_directory_parent_object->corba_Directory_file_info_list=NULL;
+               }
+
+       return r;
+}
+
+static GnomeVFSResult captive_sandbox_parent_directory_read_get1
+               (CaptiveDirectoryParentObject *captive_directory_parent_object,CaptiveFileInfoObject **file_info_captive_return)
 {
-Captive_GnomeVFSFileInfo *file_info_corba;
+xmlNode *xml_action=NULL;
+Captive_CaptiveFileInfoObject *file_info_corba;
 GnomeVFSResult r;
+CaptiveVfsParentObject *captive_vfs_parent_object;
+CaptiveFileInfoObject *file_info_captive;
+
+       g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
+       g_return_val_if_fail(file_info_captive_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+
+       captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(CAPTIVE_DIRECTORY_OBJECT(captive_directory_parent_object)->vfs);
 
-       g_return_val_if_fail(captive_directory_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
-       g_return_val_if_fail(file_info_captive!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
-       g_return_val_if_fail(captive_directory_object->dir_Handle==NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+       if (captive_vfs_parent_object->corba_bug_action) {
+               xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "directory_read",NULL);
+               xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_directory_parent_object));
+               }
 
-       Captive_Directory_read(captive_directory_object->corba_Directory_object,&file_info_corba,&captive_corba_ev);
-       if (GNOME_VFS_OK!=(r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev)))
+       Captive_Directory_read(captive_directory_parent_object->corba_Directory_object,&file_info_corba,&captive_corba_ev);
+       r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object);
+       if (xml_action)
+               xmlNewProp(xml_action,BAD_CAST "result",BAD_CAST gnome_vfs_result_to_string(r));
+       if (r!=GNOME_VFS_OK)
                return r;
 
-       if (GNOME_VFS_OK!=(r=captive_sandbox_file_info_corba_to_captive(file_info_captive,file_info_corba)))
+       r=captive_file_info_object_new(&file_info_captive);
+       if (xml_action)
+               xmlSetProp(xml_action,BAD_CAST "result",BAD_CAST gnome_vfs_result_to_string(r));
+       if (r!=GNOME_VFS_OK)
                return r;       /* 'file_info_corba' leak */
 
-       Captive_GnomeVFSFileInfo__freekids(file_info_corba,NULL/* 'd'; meaning? */);
+       r=captive_sandbox_file_info_corba_to_captive(file_info_captive,file_info_corba);
+       if (xml_action)
+               xmlSetProp(xml_action,BAD_CAST "result",BAD_CAST gnome_vfs_result_to_string(r));
+       if (r!=GNOME_VFS_OK) {
+               g_object_unref(file_info_captive);
+               return r;       /* 'file_info_corba' leak */
+               }
+
+       Captive_CaptiveFileInfoObject__freekids(file_info_corba,NULL/* 'd'; meaning? */);
        CORBA_free(file_info_corba);
 
+       *file_info_captive_return=file_info_captive;
        return GNOME_VFS_OK;
 }
 
+static GnomeVFSResult captive_sandbox_parent_directory_read_filldir(CaptiveDirectoryParentObject *captive_directory_parent_object)
+{
+CaptiveFileInfoObject *file_info_captive;
+GnomeVFSResult r;
+
+       g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
+       g_return_val_if_fail(captive_directory_parent_object->corba_Directory_file_info_list==NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+
+       for (;;) {
+               r=captive_sandbox_parent_directory_read_get1(captive_directory_parent_object,&file_info_captive);
+               if (r==GNOME_VFS_ERROR_EOF)
+                       break;
+               if (r!=GNOME_VFS_OK) {
+                       gnome_vfs_file_info_list_free(captive_directory_parent_object->corba_Directory_file_info_list);
+                       captive_directory_parent_object->corba_Directory_file_info_list=NULL;
+                       return r;
+                       }
+               captive_directory_parent_object->corba_Directory_file_info_list=g_list_prepend(
+                               captive_directory_parent_object->corba_Directory_file_info_list,file_info_captive);
+               }
 
-GnomeVFSResult captive_sandbox_parent_directory_remove(CaptiveDirectoryObject *captive_directory_object)
+       captive_directory_parent_object->corba_Directory_file_info_list=g_list_prepend(
+                       captive_directory_parent_object->corba_Directory_file_info_list,NULL);  /* EOF */
+       captive_directory_parent_object->corba_Directory_file_info_list=g_list_reverse(
+                       captive_directory_parent_object->corba_Directory_file_info_list);
+
+       return GNOME_VFS_OK;
+}
+
+/* We have to read the whole directory atomically
+ * as during valid child restart we would loose our reading position.
+ * Returned 'CaptiveFileInfoObject' has 1 reference for yourself, you must g_object_unref() it.
+ */
+GnomeVFSResult captive_sandbox_parent_directory_read
+               (CaptiveDirectoryParentObject *captive_directory_parent_object,CaptiveFileInfoObject **file_info_captive_return)
 {
 GnomeVFSResult r;
 
-       g_return_val_if_fail(captive_directory_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
-       g_return_val_if_fail(captive_directory_object->dir_Handle==NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+       g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
+       g_return_val_if_fail(file_info_captive_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+
+       if (!captive_directory_parent_object->corba_Directory_file_info_list)
+               if (GNOME_VFS_OK!=(r=captive_sandbox_parent_directory_read_filldir(captive_directory_parent_object)))
+                       return r;
+
+       if (!captive_directory_parent_object->corba_Directory_file_info_list->data) {
+               g_assert(captive_directory_parent_object->corba_Directory_file_info_list->next==NULL);
+               /* Do not clear the list to leave us stuck at EOF - GnomeVFS behaves that way. */
+               r=GNOME_VFS_ERROR_EOF;
+               }
+       else {
+               /* Cut first list item. */
+               *file_info_captive_return=captive_directory_parent_object->corba_Directory_file_info_list->data;
+               captive_directory_parent_object->corba_Directory_file_info_list=g_list_delete_link(
+                               captive_directory_parent_object->corba_Directory_file_info_list,
+                               captive_directory_parent_object->corba_Directory_file_info_list);
+               r=GNOME_VFS_OK;
+               }
+
+       return r;
+}
+
+
+GnomeVFSResult captive_sandbox_parent_directory_remove(CaptiveDirectoryParentObject *captive_directory_parent_object)
+{
+GnomeVFSResult r;
+xmlNode *xml_action=NULL;
+CaptiveVfsParentObject *captive_vfs_parent_object;
+
+       g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
+
+       captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(CAPTIVE_DIRECTORY_OBJECT(captive_directory_parent_object)->vfs);
+
+       if (captive_vfs_parent_object->corba_bug_action) {
+               xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "directory_remove",NULL);
+               xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_directory_parent_object));
+               }
 
-       Captive_Directory_remove(captive_directory_object->corba_Directory_object,&captive_corba_ev);
-       if (GNOME_VFS_OK!=(r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev)))
+       Captive_Directory_remove(captive_directory_parent_object->corba_Directory_object,&captive_corba_ev);
+       r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object);
+       if (xml_action)
+               xmlNewProp(xml_action,BAD_CAST "result",BAD_CAST gnome_vfs_result_to_string(r));
+       if (r!=GNOME_VFS_OK)
                return r;
 
        return GNOME_VFS_OK;