2 * gnome-vfs init/shutdown implementation of interface to libntfs
3 * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
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
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.
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
24 #include <ntfs/types.h> /* for 'FALSE'/'TRUE' libntfs definition */
28 #include "gnome-vfs-method.h" /* self */
29 #include <libgnomevfs/gnome-vfs-method.h>
30 #include <glib/gmessages.h>
31 #include "gnome-vfs-module.h"
32 #include <glib/ghash.h>
35 #include <ntfs/volume.h>
39 static GnomeVFSMethod GnomeVFSMethod_static;
40 G_LOCK_DEFINE_STATIC(GnomeVFSMethod_static);
43 /* map: (gchar *)method_name -> (struct method_name_info *) */
44 static GHashTable *method_name_hash;
45 G_LOCK_DEFINE_STATIC(method_name_hash);
47 struct method_name_info {
51 static void method_name_hash_key_destroy_func(gchar *key)
53 g_return_if_fail(key!=NULL);
58 static void method_name_hash_value_destroy_func(struct method_name_info *value)
60 g_return_if_fail(value!=NULL);
66 static void method_name_hash_init(void)
68 G_LOCK(method_name_hash);
69 if (!method_name_hash) {
70 method_name_hash=g_hash_table_new_full(
71 g_str_hash, /* hash_func */
72 g_str_equal, /* key_equal_func */
73 (GDestroyNotify)method_name_hash_key_destroy_func, /* key_destroy_func */
74 (GDestroyNotify)method_name_hash_value_destroy_func); /* value_destroy_func */
76 G_UNLOCK(method_name_hash);
80 /* map: (gchar *)uri_parent_string "method_name:uri_parent" -> (ntfs_volume *) */
81 static GHashTable *uri_parent_string_hash;
82 G_LOCK_DEFINE_STATIC(uri_parent_string_hash);
84 static void uri_parent_string_hash_key_destroy_func(gchar *key)
86 g_return_if_fail(key!=NULL);
91 static void uri_parent_string_hash_value_destroy_func(ntfs_volume *value)
93 g_return_if_fail(value!=NULL);
95 ntfs_umount( /* errors ignored */
97 TRUE); /* force; possibly loose modifications */
100 static void uri_parent_string_hash_init(void)
102 G_LOCK(uri_parent_string_hash);
103 if (!uri_parent_string_hash) {
104 uri_parent_string_hash=g_hash_table_new_full(
105 g_str_hash, /* hash_func */
106 g_str_equal, /* key_equal_func */
107 (GDestroyNotify)uri_parent_string_hash_key_destroy_func, /* key_destroy_func */
108 (GDestroyNotify)uri_parent_string_hash_value_destroy_func); /* value_destroy_func */
110 G_UNLOCK(uri_parent_string_hash);
114 static GnomeVFSResult libntfs_gnomevfs_uri_parent_init(ntfs_volume **volume_return,GnomeVFSURI *uri)
116 gchar *uri_parent_string;
117 gchar *uri_parent_string_parent;
120 g_return_val_if_fail(uri!=NULL,GNOME_VFS_ERROR_INVALID_URI);
121 g_return_val_if_fail(volume_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
123 uri_parent_string_hash_init();
126 return GNOME_VFS_ERROR_INVALID_URI;
127 if (!uri->text) /* not needed here but we don't permit non-specific fs-image reference */
128 return GNOME_VFS_ERROR_INVALID_URI;
129 uri_parent_string_parent=gnome_vfs_uri_to_string(uri->parent,GNOME_VFS_URI_HIDE_NONE);
130 g_assert(uri_parent_string_parent!=NULL);
132 uri_parent_string=g_strdup_printf("%s:%s",uri->method_string,uri_parent_string_parent);
133 g_assert(uri_parent_string!=NULL);
135 G_LOCK(uri_parent_string_hash);
136 volume=g_hash_table_lookup(uri_parent_string_hash,uri_parent_string);
137 G_UNLOCK(uri_parent_string_hash);
139 struct method_name_info *method_name_info;
141 G_LOCK(method_name_hash);
142 method_name_info=g_hash_table_lookup(method_name_hash,uri->method_string);
143 G_UNLOCK(method_name_hash);
144 if (!method_name_info)
145 g_return_val_if_reached(GNOME_VFS_ERROR_INVALID_URI); /* should not happend */
147 if (strcmp(uri->parent->method_string,"file")) { /* TODO: Generic GnomeVFS filter. */
148 g_free(uri_parent_string);
149 return GNOME_VFS_ERROR_INVALID_URI;
152 if (!(volume=ntfs_mount(uri->parent->text,MS_RDONLY))) {
153 g_free(uri_parent_string);
154 return GNOME_VFS_ERROR_WRONG_FORMAT;
157 G_LOCK(uri_parent_string_hash);
158 g_hash_table_insert(uri_parent_string_hash,g_strdup(uri_parent_string),volume);
159 G_UNLOCK(uri_parent_string_hash);
161 g_free(uri_parent_string);
163 *volume_return=volume;
168 static GnomeVFSResult inode_open_by_pathname(ntfs_inode **inode_return,ntfs_volume *volume,const gchar *pathname)
172 gchar *pathname_parse,*pathname_next;
175 g_return_val_if_fail(inode_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
176 g_return_val_if_fail(volume!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
177 g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
179 pathname=g_path_skip_root(pathname);
180 pathname_parse=g_alloca(strlen(pathname)+1);
181 strcpy(pathname_parse,pathname);
184 uchar_t *pathname_parse_ucs2;
188 inode=ntfs_inode_open(volume,mref);
191 return GNOME_VFS_ERROR_NOT_FOUND;
192 if (!*pathname_parse) {
196 for (pathname_next=pathname_parse;*pathname_next && *pathname_next!=G_DIR_SEPARATOR;pathname_next++);
198 *pathname_next++='\0'; /* terminate current path element */
199 while (*pathname_next==G_DIR_SEPARATOR)
201 /* FIXME: Is 'pathname' utf8? */
202 libntfs_newn(pathname_parse_ucs2,strlen(pathname_parse)+1);
203 for (i=0;pathname_parse[i];i++)
204 pathname_parse_ucs2[i]=pathname_parse[i];
205 pathname_parse_ucs2[i]=0;
207 mref=ntfs_inode_lookup_by_name(inode,pathname_parse_ucs2,i);
209 g_free(pathname_parse_ucs2);
210 if ((MFT_REF)-1==mref)
211 return GNOME_VFS_ERROR_NOT_FOUND;
213 errint=ntfs_inode_close(inode);
216 g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
217 pathname_parse=pathname_next;
223 struct libntfs_directory {
225 GList *file_info_list; /* of (GnomeVFSFileInfo *); last item has ->data==NULL */
228 static GnomeVFSResult libntfs_gnomevfs_open_directory(GnomeVFSMethod *method,
229 GnomeVFSMethodHandle **method_handle,GnomeVFSURI *uri,GnomeVFSFileInfoOptions options,GnomeVFSContext *context)
231 GnomeVFSResult errvfsresult;
234 struct libntfs_directory *libntfs_directory;
236 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
237 g_return_val_if_fail(method_handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
239 errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume,uri);
240 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
242 if (GNOME_VFS_OK!=(errvfsresult=inode_open_by_pathname(&inode,volume,uri->text)))
245 libntfs_new(libntfs_directory);
246 libntfs_directory->inode=inode;
247 libntfs_directory->file_info_list=NULL;
249 *method_handle=(GnomeVFSMethodHandle *)libntfs_directory;
254 static GnomeVFSResult libntfs_gnomevfs_close_directory(GnomeVFSMethod *method,
255 GnomeVFSMethodHandle *method_handle,GnomeVFSContext *context)
257 struct libntfs_directory *libntfs_directory;
260 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
261 libntfs_directory=(struct libntfs_directory *)method_handle;
262 g_return_val_if_fail(libntfs_directory!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
265 errint=ntfs_inode_close(libntfs_directory->inode);
268 g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
270 gnome_vfs_file_info_list_free(libntfs_directory->file_info_list);
272 g_free(libntfs_directory);
278 static gchar *libntfs_uchar_to_utf8(const uchar_t *name,const int name_len)
283 gstring=g_string_sized_new(name_len);
284 for (i=0;i<name_len;i++)
285 gstring=g_string_append_unichar(gstring,name[i]);
286 return g_string_free(gstring, /* returns utf8-formatted string */
287 FALSE); /* free_segment */
290 static int libntfs_gnomevfs_read_directory_filldir(struct libntfs_directory *libntfs_directory /* dirent */,
291 const uchar_t *name,const int name_len,const int name_type,const s64 pos,const MFT_REF mref,const unsigned dt_type)
293 GnomeVFSFileInfo *file_info;
295 g_return_val_if_fail(libntfs_directory!=NULL,-1);
296 g_return_val_if_fail(name!=NULL,-1);
297 g_return_val_if_fail(name_len>=0,-1);
298 g_return_val_if_fail(pos>=0,-1);
300 file_info=gnome_vfs_file_info_new();
301 file_info->name=libntfs_uchar_to_utf8(name,name_len);
302 file_info->valid_fields=0;
305 case NTFS_DT_FIFO: file_info->type=GNOME_VFS_FILE_TYPE_FIFO; break;
306 case NTFS_DT_CHR: file_info->type=GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE; break;
307 case NTFS_DT_DIR: file_info->type=GNOME_VFS_FILE_TYPE_DIRECTORY; break;
308 case NTFS_DT_BLK: file_info->type=GNOME_VFS_FILE_TYPE_BLOCK_DEVICE; break;
309 case NTFS_DT_REG: file_info->type=GNOME_VFS_FILE_TYPE_REGULAR; break;
310 case NTFS_DT_LNK: file_info->type=GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK; break;
311 case NTFS_DT_SOCK: file_info->type=GNOME_VFS_FILE_TYPE_SOCKET; break;
312 /* FIXME: What is 'NTFS_DT_WHT'? */
313 default: file_info->type=GNOME_VFS_FILE_TYPE_UNKNOWN;
315 if (file_info->type!=GNOME_VFS_FILE_TYPE_UNKNOWN)
316 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE;
318 libntfs_directory->file_info_list=g_list_prepend(libntfs_directory->file_info_list,file_info);
320 return 0; /* continue traversal */
324 static GnomeVFSResult libntfs_gnomevfs_read_directory(GnomeVFSMethod *method,
325 GnomeVFSMethodHandle *method_handle,GnomeVFSFileInfo *file_info,GnomeVFSContext *context)
327 GnomeVFSResult errvfsresult;
328 struct libntfs_directory *libntfs_directory;
330 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
331 libntfs_directory=(struct libntfs_directory *)method_handle;
332 g_return_val_if_fail(libntfs_directory!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
333 g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
335 if (!libntfs_directory->file_info_list) {
339 pos=0; /* read from the start; incl. "." and ".." entries */
342 libntfs_directory->inode, /* dir_ni */
344 libntfs_directory, /* dirent */
345 (ntfs_filldir_t)libntfs_gnomevfs_read_directory_filldir); /* filldir */
348 return GNOME_VFS_ERROR_INTERNAL;
350 libntfs_directory->file_info_list=g_list_prepend(libntfs_directory->file_info_list,NULL); /* EOF */
351 libntfs_directory->file_info_list=g_list_reverse(libntfs_directory->file_info_list);
354 if (!libntfs_directory->file_info_list->data) {
355 g_assert(libntfs_directory->file_info_list->next==NULL);
356 errvfsresult=GNOME_VFS_ERROR_EOF;
359 /* Cut first list item. */
360 gnome_vfs_file_info_copy(
361 file_info, /* dest */
362 libntfs_directory->file_info_list->data); /* src */
363 gnome_vfs_file_info_unref(libntfs_directory->file_info_list->data);
364 errvfsresult=GNOME_VFS_OK;
366 libntfs_directory->file_info_list=g_list_delete_link(
367 libntfs_directory->file_info_list,libntfs_directory->file_info_list);
372 struct libntfs_file {
378 static GnomeVFSResult libntfs_open_attr(struct libntfs_file *libntfs_file)
380 g_return_val_if_fail(libntfs_file!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
381 g_return_val_if_fail(libntfs_file->inode!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
383 if (!libntfs_file->attr) {
385 libntfs_file->attr=ntfs_attr_open(
386 libntfs_file->inode, /* ni */
391 if (!libntfs_file->attr)
392 return GNOME_VFS_ERROR_BAD_FILE;
399 static GnomeVFSResult libntfs_gnomevfs_open(GnomeVFSMethod *method,
400 GnomeVFSMethodHandle **method_handle_return,GnomeVFSURI *uri,GnomeVFSOpenMode mode,GnomeVFSContext *context)
402 GnomeVFSResult errvfsresult;
405 struct libntfs_file *libntfs_file;
407 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
408 g_return_val_if_fail(method_handle_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
410 errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume,uri);
411 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
413 if (mode & GNOME_VFS_OPEN_WRITE)
414 return GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM;
416 if (GNOME_VFS_OK!=(errvfsresult=inode_open_by_pathname(&inode,volume,uri->text)))
419 libntfs_new(libntfs_file);
420 libntfs_file->inode=inode;
421 libntfs_file->attr=NULL;
423 *method_handle_return=(GnomeVFSMethodHandle *)libntfs_file;
428 static GnomeVFSResult libntfs_gnomevfs_create(GnomeVFSMethod *method,
429 GnomeVFSMethodHandle **method_handle_return,GnomeVFSURI *uri,GnomeVFSOpenMode mode,gboolean exclusive,guint perm,
430 GnomeVFSContext *context)
432 GnomeVFSResult errvfsresult;
435 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
436 g_return_val_if_fail(method_handle_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
438 errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume,uri);
439 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
441 return GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM;
445 static GnomeVFSResult libntfs_gnomevfs_close(GnomeVFSMethod *method,
446 GnomeVFSMethodHandle *method_handle,GnomeVFSContext *context)
448 struct libntfs_file *libntfs_file;
451 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
452 libntfs_file=(struct libntfs_file *)method_handle;
453 g_return_val_if_fail(libntfs_file!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
455 if (libntfs_file->attr) {
457 ntfs_attr_close(libntfs_file->attr);
461 errint=ntfs_inode_close(libntfs_file->inode);
464 g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
466 g_free(libntfs_file);
472 static GnomeVFSResult libntfs_gnomevfs_read(GnomeVFSMethod *method,GnomeVFSMethodHandle *method_handle,
473 gpointer buffer,GnomeVFSFileSize num_bytes,GnomeVFSFileSize *bytes_read_return,GnomeVFSContext *context)
475 GnomeVFSResult errvfsresult;
476 struct libntfs_file *libntfs_file;
479 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
480 libntfs_file=(struct libntfs_file *)method_handle;
481 g_return_val_if_fail(libntfs_file!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
482 g_return_val_if_fail(buffer!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
483 g_return_val_if_fail(bytes_read_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
485 if (GNOME_VFS_OK!=(errvfsresult=libntfs_open_attr(libntfs_file)))
489 g_assert((GnomeVFSFileSize)count_s64==num_bytes);
491 got=ntfs_attr_pread(libntfs_file->attr,libntfs_file->pos,count_s64,buffer);
494 return GNOME_VFS_ERROR_IO;
496 libntfs_file->pos+=got;
497 *bytes_read_return=got;
498 g_assert((s64)*bytes_read_return==got);
504 static GnomeVFSResult libntfs_gnomevfs_seek(GnomeVFSMethod *method,
505 GnomeVFSMethodHandle *method_handle,GnomeVFSSeekPosition whence,GnomeVFSFileOffset offset,GnomeVFSContext *context)
507 GnomeVFSResult errvfsresult;
508 struct libntfs_file *libntfs_file;
510 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
511 libntfs_file=(struct libntfs_file *)method_handle;
512 g_return_val_if_fail(libntfs_file!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
514 if (GNOME_VFS_OK!=(errvfsresult=libntfs_open_attr(libntfs_file)))
518 case GNOME_VFS_SEEK_START:
519 libntfs_file->pos=offset;
521 case GNOME_VFS_SEEK_CURRENT:
522 libntfs_file->pos+=offset;
524 case GNOME_VFS_SEEK_END:
525 g_return_val_if_reached(GNOME_VFS_ERROR_BAD_PARAMETERS); /* FIXME: NOT IMPLEMENTED YET */
526 default: g_assert_not_reached();
532 static GnomeVFSResult libntfs_gnomevfs_tell(GnomeVFSMethod *method,
533 GnomeVFSMethodHandle *method_handle,GnomeVFSFileOffset *offset_return)
535 GnomeVFSResult errvfsresult;
536 struct libntfs_file *libntfs_file;
538 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
539 libntfs_file=(struct libntfs_file *)method_handle;
540 g_return_val_if_fail(libntfs_file!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
541 g_return_val_if_fail(offset_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
543 if (GNOME_VFS_OK!=(errvfsresult=libntfs_open_attr(libntfs_file)))
546 *offset_return=libntfs_file->pos;
547 g_assert(*offset_return==libntfs_file->pos);
553 static gboolean libntfs_gnomevfs_is_local(GnomeVFSMethod *method,const GnomeVFSURI *uri)
555 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
556 g_return_val_if_fail(uri!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
558 return gnome_vfs_uri_is_local(uri->parent);
562 GnomeVFSResult libntfs_gnomevfs_get_file_info_from_handle(GnomeVFSMethod *method,
563 GnomeVFSMethodHandle *method_handle,GnomeVFSFileInfo *file_info,GnomeVFSFileInfoOptions options,GnomeVFSContext *context)
565 GnomeVFSResult errvfsresult;
566 struct libntfs_file *libntfs_file;
568 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
569 libntfs_file=(struct libntfs_file *)method_handle;
570 g_return_val_if_fail(libntfs_file!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
571 g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
572 /* handle 'options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE'? */
574 if (GNOME_VFS_OK!=(errvfsresult=libntfs_open_attr(libntfs_file)))
577 file_info->valid_fields=0;
578 file_info->name=NULL; /* FIXME: It is complicated to read filename of open 'ntfs_inode'. */
580 file_info->size=libntfs_file->attr->data_size; /* FIXME: Is 'data_size' the right field? */
581 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_SIZE;
583 /* FIXME: We do not really know the type of 'libntfs_file'
584 * but gnome-vfs-xfer.c/copy_items() requires 'GNOME_VFS_FILE_TYPE_REGULAR'
587 file_info->type=GNOME_VFS_FILE_TYPE_REGULAR;
588 /* Do not: file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE;
589 * as gnome-vfs-xfer.c/copy_items() does not check 'GNOME_VFS_FILE_INFO_FIELDS_TYPE'
590 * and we are just bluffing we know it.
597 static GnomeVFSResult libntfs_gnomevfs_get_file_info(GnomeVFSMethod *method,
598 GnomeVFSURI *uri,GnomeVFSFileInfo *file_info,GnomeVFSFileInfoOptions options,GnomeVFSContext *context)
600 GnomeVFSResult errvfsresult;
601 GnomeVFSMethodHandle *method_handle;
603 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
604 g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
605 /* handle 'options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE'? */
607 if (GNOME_VFS_OK!=(errvfsresult=libntfs_gnomevfs_open(method,&method_handle,uri,GNOME_VFS_OPEN_READ,context)))
609 if (GNOME_VFS_OK!=(errvfsresult=libntfs_gnomevfs_get_file_info_from_handle(method,method_handle,file_info,options,context)))
611 if (GNOME_VFS_OK!=(errvfsresult=libntfs_gnomevfs_close(method,method_handle,context)))
618 GnomeVFSResult libntfs_gnomevfs_check_same_fs(GnomeVFSMethod *method,
619 GnomeVFSURI *a,GnomeVFSURI *b,gboolean *same_fs_return,GnomeVFSContext *context)
621 ntfs_volume *volume_a;
622 ntfs_volume *volume_b;
623 GnomeVFSResult errvfsresult;
625 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
626 g_return_val_if_fail(same_fs_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
628 errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume_a,a);
629 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
631 errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume_b,b);
632 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
634 *same_fs_return=(volume_a==volume_b);
641 * libntfs_gnomevfs_init:
643 * Returns: Initialized structure of #GnomeVFSMethod with static methods of libntfs-gnomevfs.
645 GnomeVFSMethod *libntfs_gnomevfs_method_init(const gchar *method_name,const gchar *args)
647 struct method_name_info *method_name_info;
649 g_return_val_if_fail(method_name!=NULL,NULL);
650 /* 'args' may be NULL if not supplied. */
652 method_name_hash_init();
654 G_LOCK(method_name_hash);
655 method_name_info=g_hash_table_lookup(method_name_hash,method_name);
656 if (method_name_info && strcmp(method_name_info->args,args))
657 method_name_info=NULL;
658 G_UNLOCK(method_name_hash);
659 if (!method_name_info) {
660 libntfs_new(method_name_info);
661 method_name_info->args=g_strdup(args);
662 G_LOCK(method_name_hash);
663 g_hash_table_replace(method_name_hash,g_strdup(method_name),method_name_info);
664 G_UNLOCK(method_name_hash);
667 G_LOCK(GnomeVFSMethod_static);
668 LIBNTFS_MEMZERO(&GnomeVFSMethod_static);
669 GnomeVFSMethod_static.method_table_size=sizeof(GnomeVFSMethod_static);
670 GnomeVFSMethod_static.open =libntfs_gnomevfs_open; /* mandatory */
671 GnomeVFSMethod_static.create =libntfs_gnomevfs_create; /* mandatory */
672 GnomeVFSMethod_static.close =libntfs_gnomevfs_close;
673 GnomeVFSMethod_static.read =libntfs_gnomevfs_read;
674 GnomeVFSMethod_static.seek =libntfs_gnomevfs_seek;
675 GnomeVFSMethod_static.tell =libntfs_gnomevfs_tell;
676 GnomeVFSMethod_static.open_directory =libntfs_gnomevfs_open_directory;
677 GnomeVFSMethod_static.close_directory =libntfs_gnomevfs_close_directory;
678 GnomeVFSMethod_static.read_directory =libntfs_gnomevfs_read_directory;
679 GnomeVFSMethod_static.get_file_info =libntfs_gnomevfs_get_file_info; /* mandatory */
680 GnomeVFSMethod_static.get_file_info_from_handle=libntfs_gnomevfs_get_file_info_from_handle;
681 GnomeVFSMethod_static.is_local =libntfs_gnomevfs_is_local; /* mandatory */
682 GnomeVFSMethod_static.check_same_fs =libntfs_gnomevfs_check_same_fs;
683 /* TODO: GnomeVFSMethodFindDirectoryFunc find_directory; */
684 /* TODO: GnomeVFSMethodFileControlFunc file_control; */
685 /* R/W: GnomeVFSMethodCreateSymbolicLinkFunc create_symbolic_link; */
686 /* R/W: GnomeVFSMethodMonitorAddFunc monitor_add; */
687 /* R/W: GnomeVFSMethodMonitorCancelFunc monitor_cancel; */
688 /* R/W: GnomeVFSMethod_static.write; */
689 /* R/W: GnomeVFSMethod_static.truncate_handle; */
690 /* R/W: GnomeVFSMethod_static.make_directory; */
691 /* R/W: GnomeVFSMethod_static.remove_directory; */
692 /* R/W: GnomeVFSMethod_static.move; */
693 /* R/W: GnomeVFSMethod_static.unlink; */
694 /* R/W: GnomeVFSMethod_static.set_file_info; */
695 /* R/W: GnomeVFSMethod_static.truncate; */
696 G_UNLOCK(GnomeVFSMethod_static);
698 return &GnomeVFSMethod_static;
703 * libntfs_gnomevfs_method_shutdown:
705 * Shutdowns libntfs-gnomevfs successfuly flushing all caches.
707 * Sad note about gnome-vfs-2.1.5 is that it never calls this function. :-)
709 void libntfs_gnomevfs_method_shutdown(void)
711 uri_parent_string_hash_init();
712 G_LOCK(uri_parent_string_hash);
713 g_hash_table_destroy(uri_parent_string_hash);
714 uri_parent_string_hash=NULL;
715 G_UNLOCK(uri_parent_string_hash);
717 method_name_hash_init();
718 G_LOCK(method_name_hash);
719 g_hash_table_destroy(method_name_hash);
720 method_name_hash=NULL;
721 G_UNLOCK(method_name_hash);