447925b6a37b31c03b585d53c836b00bf4a4c2bf
[captive.git] / src / client / gnomevfs / gnome-vfs-method.c
1 /* $Id$
2  * gnome-vfs init/shutdown implementation of interface to libcaptive
3  * Copyright (C) 2002-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 "gnome-vfs-method.h"   /* self */
23 #include "giognomevfs.h"
24 #include <libgnomevfs/gnome-vfs-method.h>
25 #include <glib/gmessages.h>
26 #include "captive/macros.h"
27 #include "gnome-vfs-module.h"
28 #include "captive/client-directory.h"
29 #include "captive/client-file.h"
30 #include "captive/client-vfs.h"
31 #include <glib/ghash.h>
32
33
34 static GnomeVFSMethod GnomeVFSMethod_static;
35 G_LOCK_DEFINE_STATIC(GnomeVFSMethod_static);
36
37
38 /* map: (gchar *)method_name -> (struct method_name_info *) */
39 static GHashTable *method_name_hash;
40 G_LOCK_DEFINE_STATIC(method_name_hash);
41
42 struct method_name_info {
43         gchar *captive_args;
44         struct captive_options captive_options;
45         };
46
47 static void method_name_hash_key_destroy_func(gchar *key)
48 {
49         g_return_if_fail(key!=NULL);
50
51         g_free(key);
52 }
53
54 static void method_name_hash_value_destroy_func(struct method_name_info *value)
55 {
56         g_return_if_fail(value!=NULL);
57
58         g_free(value->captive_args);
59         captive_options_free(&value->captive_options);
60         g_free(value);
61 }
62
63 static void method_name_hash_init(void)
64 {
65         G_LOCK(method_name_hash);
66         if (!method_name_hash) {
67                 method_name_hash=g_hash_table_new_full(
68                                 g_str_hash,     /* hash_func */
69                                 g_str_equal,    /* key_equal_func */
70                                 (GDestroyNotify)method_name_hash_key_destroy_func,      /* key_destroy_func */
71                                 (GDestroyNotify)method_name_hash_value_destroy_func);   /* value_destroy_func */
72                 }
73         G_UNLOCK(method_name_hash);
74 }
75
76
77 /* map: (gchar *)uri_parent_string "method_name:uri_parent" -> (CaptiveVfsObject *)captive_vfs_object */
78 static GHashTable *uri_parent_string_hash;
79 G_LOCK_DEFINE_STATIC(uri_parent_string_hash);
80
81 static void uri_parent_string_hash_key_destroy_func(gchar *key)
82 {
83         g_return_if_fail(key!=NULL);
84
85         g_free(key);
86 }
87
88 static void uri_parent_string_hash_value_destroy_func(CaptiveVfsObject *value)
89 {
90         g_return_if_fail(value!=NULL);
91
92         g_object_unref(value);
93 }
94
95 static void uri_parent_string_hash_init(void)
96 {
97         G_LOCK(uri_parent_string_hash);
98         if (!uri_parent_string_hash) {
99                 uri_parent_string_hash=g_hash_table_new_full(
100                                 g_str_hash,     /* hash_func */
101                                 g_str_equal,    /* key_equal_func */
102                                 (GDestroyNotify)uri_parent_string_hash_key_destroy_func,        /* key_destroy_func */
103                                 (GDestroyNotify)uri_parent_string_hash_value_destroy_func);     /* value_destroy_func */
104                 }
105         G_UNLOCK(uri_parent_string_hash);
106 }
107
108
109 static GnomeVFSResult captive_gnomevfs_uri_parent_init(CaptiveVfsObject **captive_vfs_object_return,GnomeVFSURI *uri)
110 {
111 const gchar *uri_parent_string;
112 gchar *uri_parent_string_parent;
113 GnomeVFSResult errvfsresult;
114 CaptiveVfsObject *captive_vfs_object;
115
116         g_return_val_if_fail(uri!=NULL,GNOME_VFS_ERROR_INVALID_URI);
117         g_return_val_if_fail(captive_vfs_object_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
118
119         uri_parent_string_hash_init();
120
121         if (!uri->parent)
122                 return GNOME_VFS_ERROR_INVALID_URI;
123         if (!uri->text) /* not needed here but we don't permit non-specific fs-image reference */
124                 return GNOME_VFS_ERROR_INVALID_URI;
125         uri_parent_string_parent=gnome_vfs_uri_to_string(uri->parent,GNOME_VFS_URI_HIDE_NONE);
126         g_assert(uri_parent_string_parent!=NULL);
127
128         uri_parent_string=captive_printf_alloca("%s:%s",uri->method_string,uri_parent_string_parent);
129         g_assert(uri_parent_string!=NULL);
130
131         G_LOCK(uri_parent_string_hash);
132         captive_vfs_object=g_hash_table_lookup(uri_parent_string_hash,uri_parent_string);
133         G_UNLOCK(uri_parent_string_hash);
134         if (!captive_vfs_object) {
135 struct method_name_info *method_name_info;
136 struct captive_options options_captive;
137
138                 G_LOCK(method_name_hash);
139                 method_name_info=g_hash_table_lookup(method_name_hash,uri->method_string);
140                 G_UNLOCK(method_name_hash);
141                 if (!method_name_info)
142                         g_return_val_if_reached(GNOME_VFS_ERROR_INVALID_URI);   /* should not happend */
143                 captive_options_copy(&options_captive,&method_name_info->captive_options);
144
145                 g_assert(options_captive.image_iochannel==NULL);
146                 errvfsresult=captive_gnomevfs_giognomevfs_new(
147                                 (struct captive_gnomevfs_giognomevfs **)&options_captive.image_iochannel,       /* giognomevfsp */
148                                 uri->parent,    /* uri */
149                                 options_captive.rwmode);        /* rwmode */
150                 if (errvfsresult!=GNOME_VFS_OK) {
151                         captive_options_free(&options_captive);
152                         g_assert_not_reached();
153                         return errvfsresult;
154                         }
155
156                 errvfsresult=captive_vfs_new(&captive_vfs_object,&options_captive);
157                 if (errvfsresult!=GNOME_VFS_OK) {
158                         captive_options_free(&options_captive);
159                         g_assert_not_reached();
160                         return errvfsresult;
161                         }
162                 captive_options_free(&options_captive);
163                 G_LOCK(uri_parent_string_hash);
164                 g_hash_table_insert(uri_parent_string_hash,g_strdup(uri_parent_string),captive_vfs_object);
165                 G_UNLOCK(uri_parent_string_hash);
166                 }
167
168         *captive_vfs_object_return=captive_vfs_object;
169         return GNOME_VFS_OK;
170 }
171
172
173 static GnomeVFSResult captive_gnomevfs_open_directory(GnomeVFSMethod *method,
174                 GnomeVFSMethodHandle **method_handle,GnomeVFSURI *uri,GnomeVFSFileInfoOptions options,GnomeVFSContext *context)
175 {
176 GnomeVFSResult errvfsresult;
177 CaptiveVfsObject *captive_vfs_object;
178 CaptiveDirectoryObject *captive_directory_object;
179
180         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
181         g_return_val_if_fail(method_handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
182
183         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_vfs_object,uri);
184         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
185
186         G_LOCK(libcaptive);
187         errvfsresult=captive_directory_new_open(
188                         &captive_directory_object,      /* captive_directory_object_return */
189                         captive_vfs_object,     /* captive_vfs_object */
190                         uri->text);     /* pathname */
191         G_UNLOCK(libcaptive);
192
193         *method_handle=(GnomeVFSMethodHandle *)captive_directory_object;
194         return errvfsresult;
195 }
196
197
198 static GnomeVFSResult captive_gnomevfs_close_directory(GnomeVFSMethod *method,
199                 GnomeVFSMethodHandle *method_handle,GnomeVFSContext *context)
200 {
201 CaptiveDirectoryObject *captive_directory_object;
202
203         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
204         captive_directory_object=(CaptiveDirectoryObject *)method_handle;
205         g_return_val_if_fail(CAPTIVE_DIRECTORY_IS_OBJECT(captive_directory_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
206
207         G_LOCK(libcaptive);
208         g_object_unref(captive_directory_object);
209         G_UNLOCK(libcaptive);
210
211         return GNOME_VFS_OK;
212 }
213
214
215 static GnomeVFSResult captive_gnomevfs_read_directory(GnomeVFSMethod *method,
216                 GnomeVFSMethodHandle *method_handle,GnomeVFSFileInfo *file_info,GnomeVFSContext *context)
217 {
218 GnomeVFSResult errvfsresult;
219 CaptiveDirectoryObject *captive_directory_object;
220
221         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
222         captive_directory_object=(CaptiveDirectoryObject *)method_handle;
223         g_return_val_if_fail(CAPTIVE_DIRECTORY_IS_OBJECT(captive_directory_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
224         g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
225
226         G_LOCK(libcaptive);
227         errvfsresult=captive_directory_read(captive_directory_object,file_info);
228         G_UNLOCK(libcaptive);
229
230         return errvfsresult;
231 }
232
233
234 static GnomeVFSResult captive_gnomevfs_make_directory(GnomeVFSMethod *method,
235                 GnomeVFSURI *uri,guint perm,GnomeVFSContext *context)
236 {
237 GnomeVFSResult errvfsresult;
238 CaptiveVfsObject *captive_vfs_object;
239 CaptiveDirectoryObject *captive_directory_object;
240
241         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
242
243         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_vfs_object,uri);
244         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
245
246         G_LOCK(libcaptive);
247         errvfsresult=captive_directory_new_make(
248                         &captive_directory_object,      /* captive_directory_object_return */
249                         captive_vfs_object,     /* captive_vfs_object */
250                         uri->text,      /* pathname */
251                         perm);  /* perm */
252         G_UNLOCK(libcaptive);
253         if (errvfsresult!=GNOME_VFS_OK)
254                 return errvfsresult;
255
256         G_LOCK(libcaptive);
257         g_object_unref(captive_directory_object);
258         G_UNLOCK(libcaptive);
259
260         return GNOME_VFS_OK;
261 }
262
263
264 static GnomeVFSResult captive_gnomevfs_remove_directory(GnomeVFSMethod *method,
265                 GnomeVFSURI *uri,GnomeVFSContext *context)
266 {
267 GnomeVFSResult errvfsresult;
268 CaptiveVfsObject *captive_vfs_object;
269 CaptiveDirectoryObject *captive_directory_object;
270
271         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
272
273         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_vfs_object,uri);
274         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
275
276         G_LOCK(libcaptive);
277         errvfsresult=captive_directory_new_open(
278                         &captive_directory_object,      /* captive_directory_object_return */
279                         captive_vfs_object,     /* captive_vfs_object */
280                         uri->text);     /* pathname */
281         G_UNLOCK(libcaptive);
282         if (errvfsresult!=GNOME_VFS_OK)
283                 return errvfsresult;
284
285         G_LOCK(libcaptive);
286         errvfsresult=captive_directory_remove(captive_directory_object);
287         G_UNLOCK(libcaptive);
288
289         G_LOCK(libcaptive);
290         g_object_unref(captive_directory_object);
291         G_UNLOCK(libcaptive);
292
293         return errvfsresult;
294 }
295
296
297 static GnomeVFSResult captive_gnomevfs_open(GnomeVFSMethod *method,
298                 GnomeVFSMethodHandle **method_handle_return,GnomeVFSURI *uri,GnomeVFSOpenMode mode,GnomeVFSContext *context)
299 {
300 GnomeVFSResult errvfsresult;
301 CaptiveVfsObject *captive_vfs_object;
302 CaptiveFileObject *captive_file_object;
303
304         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
305         g_return_val_if_fail(method_handle_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
306
307         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_vfs_object,uri);
308         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
309
310         G_LOCK(libcaptive);
311         errvfsresult=captive_file_new_open(
312                         &captive_file_object,   /* captive_file_object_return */
313                         captive_vfs_object,     /* captive_vfs_object */
314                         uri->text,      /* pathname */
315                         mode);  /* mode */
316         G_UNLOCK(libcaptive);
317
318         *method_handle_return=(GnomeVFSMethodHandle *)captive_file_object;
319         return errvfsresult;
320 }
321
322
323 static GnomeVFSResult captive_gnomevfs_create(GnomeVFSMethod *method,
324                 GnomeVFSMethodHandle **method_handle_return,GnomeVFSURI *uri,GnomeVFSOpenMode mode,gboolean exclusive,guint perm,
325                 GnomeVFSContext *context)
326 {
327 GnomeVFSResult errvfsresult;
328 CaptiveVfsObject *captive_vfs_object;
329 CaptiveFileObject *captive_file_object;
330
331         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
332         g_return_val_if_fail(method_handle_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
333
334         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_vfs_object,uri);
335         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
336
337         G_LOCK(libcaptive);
338         errvfsresult=captive_file_new_create(
339                         &captive_file_object,   /* captive_file_object_return */
340                         captive_vfs_object,     /* captive_vfs_object */
341                         uri->text,      /* pathname */
342                         mode,   /* mode */
343                         exclusive,      /* exclusive */
344                         perm);  /* perm */
345         G_UNLOCK(libcaptive);
346
347         *method_handle_return=(GnomeVFSMethodHandle *)captive_file_object;
348         return errvfsresult;
349 }
350
351
352 GnomeVFSResult captive_gnomevfs_unlink(GnomeVFSMethod *method,
353                 GnomeVFSURI *uri,GnomeVFSContext *context)
354 {
355 GnomeVFSResult errvfsresult;
356 CaptiveVfsObject *captive_vfs_object;
357 CaptiveFileObject *captive_file_object;
358
359         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
360
361         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_vfs_object,uri);
362         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
363
364         G_LOCK(libcaptive);
365         errvfsresult=captive_file_new_open(
366                         &captive_file_object,   /* captive_file_object_return */
367                         captive_vfs_object,     /* captive_vfs_object */
368                         uri->text,      /* pathname */
369                         (GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_RANDOM));  /* mode; is it OK? */
370         G_UNLOCK(libcaptive);
371         if (errvfsresult!=GNOME_VFS_OK)
372                 return errvfsresult;
373
374         G_LOCK(libcaptive);
375         errvfsresult=captive_file_remove(captive_file_object);
376         G_UNLOCK(libcaptive);
377
378         G_LOCK(libcaptive);
379         g_object_unref(captive_file_object);
380         G_UNLOCK(libcaptive);
381
382         return errvfsresult;
383 }
384
385
386 static GnomeVFSResult captive_gnomevfs_close(GnomeVFSMethod *method,
387                 GnomeVFSMethodHandle *method_handle,GnomeVFSContext *context)
388 {
389 CaptiveFileObject *captive_file_object;
390
391         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
392         captive_file_object=(CaptiveFileObject *)method_handle;
393         g_return_val_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
394
395         G_LOCK(libcaptive);
396         g_object_unref(captive_file_object);
397         G_UNLOCK(libcaptive);
398
399         return GNOME_VFS_OK;
400 }
401
402
403 static GnomeVFSResult captive_gnomevfs_read(GnomeVFSMethod *method,GnomeVFSMethodHandle *method_handle,
404                 gpointer buffer,GnomeVFSFileSize num_bytes,GnomeVFSFileSize *bytes_read_return,GnomeVFSContext *context)
405 {
406 GnomeVFSResult errvfsresult;
407 CaptiveFileObject *captive_file_object;
408
409         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
410         captive_file_object=(CaptiveFileObject *)method_handle;
411         g_return_val_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
412         g_return_val_if_fail(buffer!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
413         g_return_val_if_fail(bytes_read_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
414
415         G_LOCK(libcaptive);
416         errvfsresult=captive_file_read(captive_file_object,buffer,num_bytes,bytes_read_return);
417         G_UNLOCK(libcaptive);
418
419         return errvfsresult;
420 }
421
422
423 static GnomeVFSResult captive_gnomevfs_write(GnomeVFSMethod *method,GnomeVFSMethodHandle *method_handle,
424                 gconstpointer buffer,GnomeVFSFileSize num_bytes,GnomeVFSFileSize *bytes_written_return,GnomeVFSContext *context)
425 {
426 GnomeVFSResult errvfsresult;
427 CaptiveFileObject *captive_file_object;
428
429         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
430         captive_file_object=(CaptiveFileObject *)method_handle;
431         g_return_val_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
432         g_return_val_if_fail(buffer!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
433         g_return_val_if_fail(bytes_written_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
434
435         G_LOCK(libcaptive);
436         errvfsresult=captive_file_write(captive_file_object,buffer,num_bytes,bytes_written_return);
437         G_UNLOCK(libcaptive);
438
439         return errvfsresult;
440 }
441
442
443 static GnomeVFSResult captive_gnomevfs_seek(GnomeVFSMethod *method,
444                 GnomeVFSMethodHandle *method_handle,GnomeVFSSeekPosition whence,GnomeVFSFileOffset offset,GnomeVFSContext *context)
445 {
446 GnomeVFSResult errvfsresult;
447 CaptiveFileObject *captive_file_object;
448
449         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
450         captive_file_object=(CaptiveFileObject *)method_handle;
451         g_return_val_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
452
453         G_LOCK(libcaptive);
454         errvfsresult=captive_file_seek(captive_file_object,whence,offset);
455         G_UNLOCK(libcaptive);
456
457         return errvfsresult;
458 }
459
460 static GnomeVFSResult captive_gnomevfs_tell(GnomeVFSMethod *method,
461                 GnomeVFSMethodHandle *method_handle,GnomeVFSFileOffset *offset_return)
462 {
463 GnomeVFSResult errvfsresult;
464 CaptiveFileObject *captive_file_object;
465
466         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
467         captive_file_object=(CaptiveFileObject *)method_handle;
468         g_return_val_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
469         g_return_val_if_fail(offset_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
470
471         G_LOCK(libcaptive);
472         errvfsresult=captive_file_tell(captive_file_object,offset_return);
473         G_UNLOCK(libcaptive);
474
475         return errvfsresult;
476 }
477
478
479 static gboolean captive_gnomevfs_is_local(GnomeVFSMethod *method,const GnomeVFSURI *uri)
480 {
481         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
482         g_return_val_if_fail(uri!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
483
484         return gnome_vfs_uri_is_local(uri->parent);
485 }
486
487
488 static GnomeVFSResult captive_gnomevfs_get_file_info(GnomeVFSMethod *method,
489                 GnomeVFSURI *uri,GnomeVFSFileInfo *file_info,GnomeVFSFileInfoOptions options,GnomeVFSContext *context)
490 {
491 GnomeVFSResult errvfsresult;
492 CaptiveVfsObject *captive_vfs_object;
493 CaptiveFileObject *captive_file_object;
494
495         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
496         g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
497         /* handle 'options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE'? */
498
499         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_vfs_object,uri);
500         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
501
502         G_LOCK(libcaptive);
503         errvfsresult=captive_file_new_open(
504                         &captive_file_object,   /* captive_file_object_return */
505                         captive_vfs_object,     /* captive_vfs_object */
506                         uri->text,      /* pathname */
507                         0);     /* mode; 0 means FILE_READ_ATTRIBUTES */
508         G_UNLOCK(libcaptive);
509         if (errvfsresult!=GNOME_VFS_OK)
510                 return errvfsresult;
511
512         G_LOCK(libcaptive);
513         errvfsresult=captive_file_file_info_get(captive_file_object,file_info);
514         G_UNLOCK(libcaptive);
515
516         G_LOCK(libcaptive);
517         g_object_unref(captive_file_object);
518         G_UNLOCK(libcaptive);
519
520         return errvfsresult;
521 }
522
523
524 GnomeVFSResult captive_gnomevfs_get_file_info_from_handle(GnomeVFSMethod *method,
525                 GnomeVFSMethodHandle *method_handle,GnomeVFSFileInfo *file_info,GnomeVFSFileInfoOptions options,GnomeVFSContext *context)
526 {
527 GnomeVFSResult errvfsresult;
528 CaptiveFileObject *captive_file_object;
529
530         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
531         captive_file_object=(CaptiveFileObject *)method_handle;
532         g_return_val_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
533         g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
534         /* handle 'options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE'? */
535
536         G_LOCK(libcaptive);
537         errvfsresult=captive_file_file_info_get(captive_file_object,file_info);
538         G_UNLOCK(libcaptive);
539
540         return errvfsresult;
541 }
542
543
544 GnomeVFSResult captive_gnomevfs_truncate_handle(GnomeVFSMethod *method,
545                 GnomeVFSMethodHandle *handle,GnomeVFSFileSize length,GnomeVFSContext *context)
546 {
547 GnomeVFSResult errvfsresult;
548 CaptiveFileObject *captive_file_object;
549
550         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
551         captive_file_object=(CaptiveFileObject *)handle;
552         g_return_val_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object),GNOME_VFS_ERROR_BAD_PARAMETERS);
553
554         G_LOCK(libcaptive);
555         errvfsresult=captive_file_truncate(captive_file_object,length);
556         G_UNLOCK(libcaptive);
557
558         return errvfsresult;
559 }
560
561 GnomeVFSResult captive_gnomevfs_truncate(GnomeVFSMethod *method,
562                 GnomeVFSURI *uri,GnomeVFSFileSize length,GnomeVFSContext *context)
563 {
564 GnomeVFSResult errvfsresult;
565 CaptiveVfsObject *captive_vfs_object;
566 CaptiveFileObject *captive_file_object;
567
568         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
569
570         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_vfs_object,uri);
571         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
572
573         G_LOCK(libcaptive);
574         errvfsresult=captive_file_new_open(
575                         &captive_file_object,   /* captive_file_object_return */
576                         captive_vfs_object,     /* captive_vfs_object */
577                         uri->text,      /* pathname */
578                         (GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_RANDOM));  /* mode; is it OK? */
579         G_UNLOCK(libcaptive);
580         if (errvfsresult!=GNOME_VFS_OK)
581                 return errvfsresult;
582
583         G_LOCK(libcaptive);
584         errvfsresult=captive_file_truncate(captive_file_object,length);
585         G_UNLOCK(libcaptive);
586
587         G_LOCK(libcaptive);
588         g_object_unref(captive_file_object);
589         G_UNLOCK(libcaptive);
590
591         return errvfsresult;
592 }
593
594
595 GnomeVFSResult captive_gnomevfs_move(GnomeVFSMethod *method,
596                 GnomeVFSURI *old_uri,GnomeVFSURI *new_uri,gboolean force_replace,GnomeVFSContext *context)
597 {
598 GnomeVFSResult errvfsresult;
599 CaptiveVfsObject *captive_old_vfs_object;
600 CaptiveVfsObject *captive_new_vfs_object;
601 CaptiveFileObject *captive_old_file_object;
602
603         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
604
605         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_old_vfs_object,old_uri);
606         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
607
608         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_new_vfs_object,new_uri);
609         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
610
611         if (captive_old_vfs_object!=captive_new_vfs_object)
612                 return GNOME_VFS_ERROR_NOT_SAME_FILE_SYSTEM;
613
614         G_LOCK(libcaptive);
615         errvfsresult=captive_file_new_open(
616                         &captive_old_file_object,       /* captive_file_object_return */
617                         captive_old_vfs_object, /* captive_vfs_object; ==captive_new_vfs_object */
618                         old_uri->text,  /* pathname */
619                         (GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_WRITE));  /* mode; is it OK? */
620         G_UNLOCK(libcaptive);
621         if (errvfsresult!=GNOME_VFS_OK)
622                 return errvfsresult;
623
624         G_LOCK(libcaptive);
625         errvfsresult=captive_file_move(captive_old_file_object,new_uri->text,force_replace);
626         G_UNLOCK(libcaptive);
627
628         G_LOCK(libcaptive);
629         g_object_unref(captive_old_file_object);
630         G_UNLOCK(libcaptive);
631
632         return errvfsresult;
633 }
634
635
636 GnomeVFSResult captive_gnomevfs_check_same_fs(GnomeVFSMethod *method,
637                 GnomeVFSURI *a,GnomeVFSURI *b,gboolean *same_fs_return,GnomeVFSContext *context)
638 {
639 CaptiveVfsObject *captive_vfs_object_a;
640 CaptiveVfsObject *captive_vfs_object_b;
641 GnomeVFSResult errvfsresult;
642
643         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
644         g_return_val_if_fail(same_fs_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
645
646         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_vfs_object_a,a);
647         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
648
649         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_vfs_object_b,b);
650         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
651
652         *same_fs_return=(captive_vfs_object_a==captive_vfs_object_b);
653
654         return GNOME_VFS_OK;
655 }
656
657
658 GnomeVFSResult captive_gnomevfs_set_file_info(GnomeVFSMethod *method,
659                 GnomeVFSURI *a,const GnomeVFSFileInfo *info,GnomeVFSSetFileInfoMask mask,GnomeVFSContext *context)
660 {
661 GnomeVFSResult errvfsresult;
662 CaptiveVfsObject *captive_vfs_object;
663 CaptiveFileObject *captive_file_object;
664
665         g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
666         g_return_val_if_fail(info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
667
668         errvfsresult=captive_gnomevfs_uri_parent_init(&captive_vfs_object,a);
669         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
670
671         G_LOCK(libcaptive);
672         errvfsresult=captive_file_new_open(
673                         &captive_file_object,   /* captive_file_object_return */
674                         captive_vfs_object,     /* captive_vfs_object */
675                         a->text,        /* pathname */
676                         (GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_RANDOM));        /* mode; is it OK? */
677         G_UNLOCK(libcaptive);
678         if (errvfsresult!=GNOME_VFS_OK)
679                 return errvfsresult;
680
681         G_LOCK(libcaptive);
682         errvfsresult=captive_file_file_info_set(captive_file_object,info,mask);
683         G_UNLOCK(libcaptive);
684
685         G_LOCK(libcaptive);
686         g_object_unref(captive_file_object);
687         G_UNLOCK(libcaptive);
688
689         return errvfsresult;
690 }
691
692
693 /**
694  * captive_gnomevfs_init:
695  *
696  * Returns: Initialized structure of #GnomeVFSMethod with static methods of libcaptive-gnomevfs.
697  */
698 GnomeVFSMethod *captive_gnomevfs_method_init(const gchar *method_name,const gchar *captive_args)
699 {
700 struct method_name_info *method_name_info;
701
702         g_return_val_if_fail(method_name!=NULL,NULL);
703         g_return_val_if_fail(captive_args!=NULL,NULL);
704
705         method_name_hash_init();
706
707         G_LOCK(method_name_hash);
708         method_name_info=g_hash_table_lookup(method_name_hash,method_name);
709         if (method_name_info && strcmp(method_name_info->captive_args,captive_args))
710                 method_name_info=NULL;
711         G_UNLOCK(method_name_hash);
712         if (!method_name_info) {
713                 captive_new(method_name_info);
714                 method_name_info->captive_args=g_strdup(captive_args);
715                 captive_options_init(&method_name_info->captive_options);
716                 if (!captive_options_parse(&method_name_info->captive_options,captive_args)) {
717                         g_assert_not_reached();
718                         g_free(method_name_info->captive_args);
719                         g_free(method_name_info);
720                         return NULL;
721                         }
722                 G_LOCK(method_name_hash);
723                 g_hash_table_replace(method_name_hash,g_strdup(method_name),method_name_info);
724                 G_UNLOCK(method_name_hash);
725                 }
726
727         G_LOCK(GnomeVFSMethod_static);
728         CAPTIVE_MEMZERO(&GnomeVFSMethod_static);
729         GnomeVFSMethod_static.method_table_size=sizeof(GnomeVFSMethod_static);
730         GnomeVFSMethod_static.open                     =captive_gnomevfs_open;  /* mandatory */
731         GnomeVFSMethod_static.create                   =captive_gnomevfs_create;        /* mandatory */
732         GnomeVFSMethod_static.close                    =captive_gnomevfs_close;
733         GnomeVFSMethod_static.read                     =captive_gnomevfs_read;
734         GnomeVFSMethod_static.write                    =captive_gnomevfs_write;
735         GnomeVFSMethod_static.seek                     =captive_gnomevfs_seek;
736         GnomeVFSMethod_static.tell                     =captive_gnomevfs_tell;
737         GnomeVFSMethod_static.truncate_handle          =captive_gnomevfs_truncate_handle;
738         GnomeVFSMethod_static.open_directory           =captive_gnomevfs_open_directory;
739         GnomeVFSMethod_static.close_directory          =captive_gnomevfs_close_directory;
740         GnomeVFSMethod_static.read_directory           =captive_gnomevfs_read_directory;
741         GnomeVFSMethod_static.get_file_info            =captive_gnomevfs_get_file_info; /* mandatory */
742         GnomeVFSMethod_static.get_file_info_from_handle=captive_gnomevfs_get_file_info_from_handle;
743         GnomeVFSMethod_static.is_local                 =captive_gnomevfs_is_local;      /* mandatory */
744         GnomeVFSMethod_static.make_directory           =captive_gnomevfs_make_directory;
745         GnomeVFSMethod_static.remove_directory         =captive_gnomevfs_remove_directory;
746         GnomeVFSMethod_static.move                     =captive_gnomevfs_move;
747         GnomeVFSMethod_static.unlink                   =captive_gnomevfs_unlink;
748         GnomeVFSMethod_static.check_same_fs            =captive_gnomevfs_check_same_fs;
749         GnomeVFSMethod_static.set_file_info            =captive_gnomevfs_set_file_info;
750         GnomeVFSMethod_static.truncate                 =captive_gnomevfs_truncate;
751         /* TODO: GnomeVFSMethodFindDirectoryFunc find_directory; */
752         /* TODO: GnomeVFSMethodCreateSymbolicLinkFunc create_symbolic_link; */
753         /* TODO: GnomeVFSMethodMonitorAddFunc monitor_add; */
754         /* TODO: GnomeVFSMethodMonitorCancelFunc monitor_cancel; */
755         /* TODO: GnomeVFSMethodFileControlFunc file_control; */
756         G_UNLOCK(GnomeVFSMethod_static);
757
758         return &GnomeVFSMethod_static;
759 }
760
761
762 /**
763  * captive_gnomevfs_method_shutdown:
764  *
765  * Shutdowns libcaptive-gnomevfs successfuly flushing all caches.
766  *
767  * This operation may not completely clean up the process space
768  * if libcaptive #sandbox is not in use.
769  *
770  * Sad note about gnome-vfs-2.1.5 is that it never calls this function. :-)
771  */ 
772 void captive_gnomevfs_method_shutdown(void)
773 {
774         uri_parent_string_hash_init();
775         G_LOCK(uri_parent_string_hash);
776         g_hash_table_destroy(uri_parent_string_hash);
777         uri_parent_string_hash=NULL;
778         G_UNLOCK(uri_parent_string_hash);
779
780         method_name_hash_init();
781         G_LOCK(method_name_hash);
782         g_hash_table_destroy(method_name_hash);
783         method_name_hash=NULL;
784         G_UNLOCK(method_name_hash);
785 }