Implemented sub-second W32 filesystem interface by new: CaptiveFileInfoObject
[captive.git] / src / libcaptive / sandbox / parent-Directory.c
1 /* $Id$
2  * CORBA/ORBit client side of Directory 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-Directory.h"   /* self */
23 #include <glib/gmessages.h>
24 #include "split.h"
25 #include "sandbox.h"
26 #include "../client/directory.h"
27 #include "../client/vfs.h"
28 #include "FileInfo.h"
29 #include "captive/macros.h"
30 #include "../client/vfs-parent.h"
31 #include "captive/client-file-info.h"
32
33
34 GnomeVFSResult captive_sandbox_parent_directory_new_open
35                 (CaptiveDirectoryParentObject *captive_directory_parent_object)
36 {
37 xmlNode *xml_action=NULL;
38 CaptiveVfsParentObject *captive_vfs_parent_object;
39 GnomeVFSResult r;
40 Captive_Directory corba_Directory_object;
41
42         g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
43         g_return_val_if_fail(captive_directory_parent_object->pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
44
45         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(CAPTIVE_DIRECTORY_OBJECT(captive_directory_parent_object)->vfs);
46
47         if (captive_vfs_parent_object->corba_bug_action) {
48                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "directory_new_open",NULL);
49                 xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_directory_parent_object));
50                 xmlNewProp(xml_action,BAD_CAST "pathname",BAD_CAST captive_directory_parent_object->pathname);
51                 }
52
53         corba_Directory_object=Captive_Vfs_directory_new_open(
54                         captive_vfs_parent_object->corba_Vfs_object,captive_directory_parent_object->pathname,&captive_corba_ev);
55         if (xml_action)
56                 xmlNewProp(xml_action,BAD_CAST "result",BAD_CAST (captive_corba_ev._major==CORBA_NO_EXCEPTION ? "1" : "0"));
57         /* If 'r' means failure 'corba_Directory_object' may not be 'CORBA_OBJECT_NIL'
58          * although it is not valid 'CORBA_Object' to be passed to CORBA_Object_release().
59          */
60         if (GNOME_VFS_OK!=(r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object)))
61                 return r;
62
63         captive_directory_parent_object->corba_Directory_object=corba_Directory_object;
64         return GNOME_VFS_OK;
65 }
66
67
68 GnomeVFSResult captive_sandbox_parent_directory_new_make
69                 (CaptiveDirectoryParentObject *captive_directory_parent_object,guint perm)
70 {
71 xmlNode *xml_action=NULL;
72 CaptiveVfsParentObject *captive_vfs_parent_object;
73 GnomeVFSResult r;
74 Captive_Directory corba_Directory_object;
75
76         g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
77         g_return_val_if_fail(captive_directory_parent_object->pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
78
79         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(CAPTIVE_DIRECTORY_OBJECT(captive_directory_parent_object)->vfs);
80
81         if (captive_vfs_parent_object->corba_bug_action) {
82                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "directory_new_make",NULL);
83                 xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_directory_parent_object));
84                 xmlNewProp(xml_action,BAD_CAST "pathname",BAD_CAST captive_directory_parent_object->pathname);
85                 xmlNewProp(xml_action,BAD_CAST "perm",BAD_CAST captive_printf_alloca("%u",(unsigned)perm));
86                 }
87
88         corba_Directory_object=Captive_Vfs_directory_new_make(
89                         captive_vfs_parent_object->corba_Vfs_object,captive_directory_parent_object->pathname,perm,&captive_corba_ev);
90         if (xml_action)
91                 xmlNewProp(xml_action,BAD_CAST "result",BAD_CAST (captive_corba_ev._major==CORBA_NO_EXCEPTION ? "1" : "0"));
92         /* If 'r' means failure 'corba_Directory_object' may not be 'CORBA_OBJECT_NIL'
93          * although it is not valid 'CORBA_Object' to be passed to CORBA_Object_release().
94          */
95         if (GNOME_VFS_OK!=(r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object)))
96                 return r;
97
98         captive_directory_parent_object->corba_Directory_object=corba_Directory_object;
99         return GNOME_VFS_OK;
100 }
101
102
103 GnomeVFSResult captive_sandbox_parent_directory_close(CaptiveDirectoryParentObject *captive_directory_parent_object)
104 {
105 GnomeVFSResult r;
106 xmlNode *xml_action=NULL;
107 CaptiveVfsParentObject *captive_vfs_parent_object;
108
109         g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
110
111         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(CAPTIVE_DIRECTORY_OBJECT(captive_directory_parent_object)->vfs);
112
113         if (captive_vfs_parent_object->corba_bug_action) {
114                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "directory_close",NULL);
115                 xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_directory_parent_object));
116                 }
117
118         Captive_Directory_shutdown(captive_directory_parent_object->corba_Directory_object,&captive_corba_ev);
119         r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object);
120         if (xml_action)
121                 xmlNewProp(xml_action,BAD_CAST "result",BAD_CAST gnome_vfs_result_to_string(r));
122
123         /* Always clear 'corba_Directory_object' even if 'r' means failure. */
124         CORBA_Object_release((CORBA_Object)captive_directory_parent_object->corba_Directory_object,&captive_corba_ev);
125         captive_directory_parent_object->corba_Directory_object=CORBA_OBJECT_NIL;
126
127         if (captive_directory_parent_object->corba_Directory_file_info_list) {
128 GList *file_info_last_l=g_list_last(captive_directory_parent_object->corba_Directory_file_info_list);
129
130                 /* Prevent gnome_vfs_file_info_list_free() and its gnome_vfs_file_info_unref()
131                  * on the last 'file_info_list' items as it is EOF with NULL '->data'.
132                  */
133                 /* Do not: g_assert(file_info_last_l->data==NULL);      * directory EOF *
134                  * as the crashed client may not produced the trailing NULL.
135                  */
136                 if (!file_info_last_l->data)
137                         captive_directory_parent_object->corba_Directory_file_info_list=g_list_delete_link(
138                                         captive_directory_parent_object->corba_Directory_file_info_list,file_info_last_l);
139                 gnome_vfs_file_info_list_free(captive_directory_parent_object->corba_Directory_file_info_list);
140                 captive_directory_parent_object->corba_Directory_file_info_list=NULL;
141                 }
142
143         return r;
144 }
145
146 static GnomeVFSResult captive_sandbox_parent_directory_read_get1
147                 (CaptiveDirectoryParentObject *captive_directory_parent_object,CaptiveFileInfoObject **file_info_captive_return)
148 {
149 xmlNode *xml_action=NULL;
150 Captive_CaptiveFileInfoObject *file_info_corba;
151 GnomeVFSResult r;
152 CaptiveVfsParentObject *captive_vfs_parent_object;
153 CaptiveFileInfoObject *file_info_captive;
154
155         g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
156         g_return_val_if_fail(file_info_captive_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
157
158         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(CAPTIVE_DIRECTORY_OBJECT(captive_directory_parent_object)->vfs);
159
160         if (captive_vfs_parent_object->corba_bug_action) {
161                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "directory_read",NULL);
162                 xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_directory_parent_object));
163                 }
164
165         Captive_Directory_read(captive_directory_parent_object->corba_Directory_object,&file_info_corba,&captive_corba_ev);
166         r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object);
167         if (xml_action)
168                 xmlNewProp(xml_action,BAD_CAST "result",BAD_CAST gnome_vfs_result_to_string(r));
169         if (r!=GNOME_VFS_OK)
170                 return r;
171
172         r=captive_file_info_object_new(&file_info_captive);
173         if (xml_action)
174                 xmlSetProp(xml_action,BAD_CAST "result",BAD_CAST gnome_vfs_result_to_string(r));
175         if (r!=GNOME_VFS_OK)
176                 return r;       /* 'file_info_corba' leak */
177
178         r=captive_sandbox_file_info_corba_to_captive(file_info_captive,file_info_corba);
179         if (xml_action)
180                 xmlSetProp(xml_action,BAD_CAST "result",BAD_CAST gnome_vfs_result_to_string(r));
181         if (r!=GNOME_VFS_OK) {
182                 g_object_unref(file_info_captive);
183                 return r;       /* 'file_info_corba' leak */
184                 }
185
186         Captive_CaptiveFileInfoObject__freekids(file_info_corba,NULL/* 'd'; meaning? */);
187         CORBA_free(file_info_corba);
188
189         *file_info_captive_return=file_info_captive;
190         return GNOME_VFS_OK;
191 }
192
193 static GnomeVFSResult captive_sandbox_parent_directory_read_filldir(CaptiveDirectoryParentObject *captive_directory_parent_object)
194 {
195 CaptiveFileInfoObject *file_info_captive;
196 GnomeVFSResult r;
197
198         g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
199         g_return_val_if_fail(captive_directory_parent_object->corba_Directory_file_info_list==NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
200
201         for (;;) {
202                 r=captive_sandbox_parent_directory_read_get1(captive_directory_parent_object,&file_info_captive);
203                 if (r==GNOME_VFS_ERROR_EOF)
204                         break;
205                 if (r!=GNOME_VFS_OK) {
206                         gnome_vfs_file_info_list_free(captive_directory_parent_object->corba_Directory_file_info_list);
207                         captive_directory_parent_object->corba_Directory_file_info_list=NULL;
208                         return r;
209                         }
210                 captive_directory_parent_object->corba_Directory_file_info_list=g_list_prepend(
211                                 captive_directory_parent_object->corba_Directory_file_info_list,file_info_captive);
212                 }
213
214         captive_directory_parent_object->corba_Directory_file_info_list=g_list_prepend(
215                         captive_directory_parent_object->corba_Directory_file_info_list,NULL);  /* EOF */
216         captive_directory_parent_object->corba_Directory_file_info_list=g_list_reverse(
217                         captive_directory_parent_object->corba_Directory_file_info_list);
218
219         return GNOME_VFS_OK;
220 }
221
222 /* We have to read the whole directory atomically
223  * as during valid child restart we would loose our reading position.
224  * Returned 'CaptiveFileInfoObject' has 1 reference for yourself, you must g_object_unref() it.
225  */
226 GnomeVFSResult captive_sandbox_parent_directory_read
227                 (CaptiveDirectoryParentObject *captive_directory_parent_object,CaptiveFileInfoObject **file_info_captive_return)
228 {
229 GnomeVFSResult r;
230
231         g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
232         g_return_val_if_fail(file_info_captive_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
233
234         if (!captive_directory_parent_object->corba_Directory_file_info_list)
235                 if (GNOME_VFS_OK!=(r=captive_sandbox_parent_directory_read_filldir(captive_directory_parent_object)))
236                         return r;
237
238         if (!captive_directory_parent_object->corba_Directory_file_info_list->data) {
239                 g_assert(captive_directory_parent_object->corba_Directory_file_info_list->next==NULL);
240                 /* Do not clear the list to leave us stuck at EOF - GnomeVFS behaves that way. */
241                 r=GNOME_VFS_ERROR_EOF;
242                 }
243         else {
244                 /* Cut first list item. */
245                 *file_info_captive_return=captive_directory_parent_object->corba_Directory_file_info_list->data;
246                 captive_directory_parent_object->corba_Directory_file_info_list=g_list_delete_link(
247                                 captive_directory_parent_object->corba_Directory_file_info_list,
248                                 captive_directory_parent_object->corba_Directory_file_info_list);
249                 r=GNOME_VFS_OK;
250                 }
251
252         return r;
253 }
254
255
256 GnomeVFSResult captive_sandbox_parent_directory_remove(CaptiveDirectoryParentObject *captive_directory_parent_object)
257 {
258 GnomeVFSResult r;
259 xmlNode *xml_action=NULL;
260 CaptiveVfsParentObject *captive_vfs_parent_object;
261
262         g_return_val_if_fail(CAPTIVE_DIRECTORY_PARENT_IS_OBJECT(captive_directory_parent_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
263
264         captive_vfs_parent_object=CAPTIVE_VFS_PARENT_OBJECT(CAPTIVE_DIRECTORY_OBJECT(captive_directory_parent_object)->vfs);
265
266         if (captive_vfs_parent_object->corba_bug_action) {
267                 xml_action=xmlNewTextChild(captive_vfs_parent_object->corba_bug_action,NULL,BAD_CAST "directory_remove",NULL);
268                 xmlNewProp(xml_action,BAD_CAST "object",BAD_CAST captive_printf_alloca("%p",captive_directory_parent_object));
269                 }
270
271         Captive_Directory_remove(captive_directory_parent_object->corba_Directory_object,&captive_corba_ev);
272         r=captive_sandbox_parent_return_from_CORBA_Environment(&captive_corba_ev,captive_vfs_parent_object);
273         if (xml_action)
274                 xmlNewProp(xml_action,BAD_CAST "result",BAD_CAST gnome_vfs_result_to_string(r));
275         if (r!=GNOME_VFS_OK)
276                 return r;
277
278         return GNOME_VFS_OK;
279 }