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; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <ntfs/types.h> /* for 'FALSE'/'TRUE' libntfs definition */
29 #include "gnome-vfs-method.h" /* self */
30 #include <libgnomevfs/gnome-vfs-method.h>
31 #include <glib/gmessages.h>
32 #include "gnome-vfs-module.h"
33 #include <glib/ghash.h>
35 #include <libgnomevfs/gnome-vfs-utils.h>
37 #include <ntfs/volume.h>
41 static GnomeVFSMethod GnomeVFSMethod_static;
42 G_LOCK_DEFINE_STATIC(GnomeVFSMethod_static);
45 /* map: (gchar *)method_name -> (struct method_name_info *) */
46 static GHashTable *method_name_hash;
47 G_LOCK_DEFINE_STATIC(method_name_hash);
49 struct method_name_info {
53 static void method_name_hash_key_destroy_func(gchar *key)
55 g_return_if_fail(key!=NULL);
60 static void method_name_hash_value_destroy_func(struct method_name_info *value)
62 g_return_if_fail(value!=NULL);
68 static void method_name_hash_init(void)
70 G_LOCK(method_name_hash);
71 if (!method_name_hash) {
72 method_name_hash=g_hash_table_new_full(
73 g_str_hash, /* hash_func */
74 g_str_equal, /* key_equal_func */
75 (GDestroyNotify)method_name_hash_key_destroy_func, /* key_destroy_func */
76 (GDestroyNotify)method_name_hash_value_destroy_func); /* value_destroy_func */
78 G_UNLOCK(method_name_hash);
82 /* map: (gchar *)uri_parent_string "method_name:uri_parent" -> (ntfs_volume *) */
83 static GHashTable *uri_parent_string_hash;
84 G_LOCK_DEFINE_STATIC(uri_parent_string_hash);
86 static void uri_parent_string_hash_key_destroy_func(gchar *key)
88 g_return_if_fail(key!=NULL);
93 static void uri_parent_string_hash_value_destroy_func(ntfs_volume *value)
95 g_return_if_fail(value!=NULL);
97 ntfs_umount( /* errors ignored */
99 TRUE); /* force; possibly loose modifications */
102 static void uri_parent_string_hash_init(void)
104 G_LOCK(uri_parent_string_hash);
105 if (!uri_parent_string_hash) {
106 uri_parent_string_hash=g_hash_table_new_full(
107 g_str_hash, /* hash_func */
108 g_str_equal, /* key_equal_func */
109 (GDestroyNotify)uri_parent_string_hash_key_destroy_func, /* key_destroy_func */
110 (GDestroyNotify)uri_parent_string_hash_value_destroy_func); /* value_destroy_func */
112 G_UNLOCK(uri_parent_string_hash);
116 static GnomeVFSResult libntfs_gnomevfs_uri_parent_init(ntfs_volume **volume_return,GnomeVFSURI *uri)
118 gchar *uri_parent_string;
119 gchar *uri_parent_string_parent;
122 g_return_val_if_fail(uri!=NULL,GNOME_VFS_ERROR_INVALID_URI);
123 g_return_val_if_fail(volume_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
125 uri_parent_string_hash_init();
128 return GNOME_VFS_ERROR_INVALID_URI;
129 if (!uri->text) /* not needed here but we don't permit non-specific fs-image reference */
130 return GNOME_VFS_ERROR_INVALID_URI;
131 uri_parent_string_parent=gnome_vfs_uri_to_string(uri->parent,GNOME_VFS_URI_HIDE_NONE);
132 g_assert(uri_parent_string_parent!=NULL);
134 uri_parent_string=g_strdup_printf("%s:%s",uri->method_string,uri_parent_string_parent);
135 g_assert(uri_parent_string!=NULL);
137 G_LOCK(uri_parent_string_hash);
138 volume=g_hash_table_lookup(uri_parent_string_hash,uri_parent_string);
139 G_UNLOCK(uri_parent_string_hash);
141 struct method_name_info *method_name_info;
143 G_LOCK(method_name_hash);
144 method_name_info=g_hash_table_lookup(method_name_hash,uri->method_string);
145 G_UNLOCK(method_name_hash);
146 if (!method_name_info)
147 g_return_val_if_reached(GNOME_VFS_ERROR_INVALID_URI); /* should not happend */
149 if (strcmp(uri->parent->method_string,"file")) { /* TODO: Generic GnomeVFS filter. */
150 g_free(uri_parent_string);
151 return GNOME_VFS_ERROR_INVALID_URI;
154 if (!(volume=ntfs_mount(uri->parent->text,MS_RDONLY))) {
155 g_free(uri_parent_string);
156 return GNOME_VFS_ERROR_WRONG_FORMAT;
159 G_LOCK(uri_parent_string_hash);
160 g_hash_table_insert(uri_parent_string_hash,g_strdup(uri_parent_string),volume);
161 G_UNLOCK(uri_parent_string_hash);
163 g_free(uri_parent_string);
165 *volume_return=volume;
170 static GnomeVFSResult inode_open_by_pathname(ntfs_inode **inode_return,ntfs_volume *volume,const gchar *pathname)
174 gchar *pathname_parse,*pathname_next;
177 g_return_val_if_fail(inode_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
178 g_return_val_if_fail(volume!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
179 g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
181 pathname=g_path_skip_root(pathname);
182 pathname_parse=g_alloca(strlen(pathname)+1);
183 strcpy(pathname_parse,pathname);
186 uchar_t *pathname_parse_ucs2;
187 gchar *pathname_parse_unescaped;
191 inode=ntfs_inode_open(volume,mref);
194 return GNOME_VFS_ERROR_NOT_FOUND;
195 if (!*pathname_parse) {
199 for (pathname_next=pathname_parse;*pathname_next && *pathname_next!=G_DIR_SEPARATOR;pathname_next++);
201 *pathname_next++='\0'; /* terminate current path element */
202 while (*pathname_next==G_DIR_SEPARATOR)
204 /* FIXME: Is 'pathname' utf8? */
205 pathname_parse_unescaped=gnome_vfs_unescape_string(pathname_parse,
206 NULL); /* illegal_characters */
207 libntfs_newn(pathname_parse_ucs2,strlen(pathname_parse_unescaped)+1);
208 for (i=0;pathname_parse_unescaped[i];i++)
209 pathname_parse_ucs2[i]=pathname_parse_unescaped[i];
210 pathname_parse_ucs2[i]=0;
211 g_free(pathname_parse_unescaped);
213 mref=ntfs_inode_lookup_by_name(inode,pathname_parse_ucs2,i);
215 g_free(pathname_parse_ucs2);
216 if ((MFT_REF)-1==mref)
217 return GNOME_VFS_ERROR_NOT_FOUND;
219 errint=ntfs_inode_close(inode);
222 g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
223 pathname_parse=pathname_next;
229 struct libntfs_directory {
231 GList *file_info_list; /* of (GnomeVFSFileInfo *); last item has ->data==NULL */
234 static GnomeVFSResult libntfs_gnomevfs_open_directory(GnomeVFSMethod *method,
235 GnomeVFSMethodHandle **method_handle,GnomeVFSURI *uri,GnomeVFSFileInfoOptions options,GnomeVFSContext *context)
237 GnomeVFSResult errvfsresult;
240 struct libntfs_directory *libntfs_directory;
242 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
243 g_return_val_if_fail(method_handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
245 if (GNOME_VFS_OK!=(errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume,uri)))
248 if (GNOME_VFS_OK!=(errvfsresult=inode_open_by_pathname(&inode,volume,uri->text)))
251 libntfs_new(libntfs_directory);
252 libntfs_directory->inode=inode;
253 libntfs_directory->file_info_list=NULL;
255 *method_handle=(GnomeVFSMethodHandle *)libntfs_directory;
260 static GnomeVFSResult libntfs_gnomevfs_close_directory(GnomeVFSMethod *method,
261 GnomeVFSMethodHandle *method_handle,GnomeVFSContext *context)
263 struct libntfs_directory *libntfs_directory;
266 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
267 libntfs_directory=(struct libntfs_directory *)method_handle;
268 g_return_val_if_fail(libntfs_directory!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
271 errint=ntfs_inode_close(libntfs_directory->inode);
274 g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
276 if (libntfs_directory->file_info_list) {
279 /* Prevent gnome_vfs_file_info_list_free() and its gnome_vfs_file_info_unref()
280 * on the last 'file_info_list' items as it is EOF with NULL '->data'.
282 last_l=g_list_last(libntfs_directory->file_info_list);
283 g_assert(last_l->data==NULL);
284 libntfs_directory->file_info_list=g_list_delete_link(libntfs_directory->file_info_list,last_l);
285 gnome_vfs_file_info_list_free(libntfs_directory->file_info_list);
288 g_free(libntfs_directory);
294 static gchar *libntfs_uchar_to_utf8(const uchar_t *name,const int name_len)
299 gstring=g_string_sized_new(name_len);
300 for (i=0;i<name_len;i++)
301 gstring=g_string_append_unichar(gstring,name[i]);
302 return g_string_free(gstring, /* returns utf8-formatted string */
303 FALSE); /* free_segment */
306 /* Do not lock 'libntfs' here as we are already locked
307 * inside ntfs_readdir().
309 static int libntfs_gnomevfs_read_directory_filldir(struct libntfs_directory *libntfs_directory /* dirent */,
310 const uchar_t *name,const int name_len,const int name_type,const s64 pos,const MFT_REF mref,const unsigned dt_type)
312 GnomeVFSFileInfo *file_info;
314 g_return_val_if_fail(libntfs_directory!=NULL,-1);
315 g_return_val_if_fail(name!=NULL,-1);
316 g_return_val_if_fail(name_len>=0,-1);
317 g_return_val_if_fail(pos>=0,-1);
319 if (name_len>0 && name[0]=='$') /* system directory; FIXME: What is its proper identification? */
320 return 0; /* continue traversal */
322 file_info=gnome_vfs_file_info_new();
323 file_info->name=libntfs_uchar_to_utf8(name,name_len);
324 file_info->valid_fields=0;
327 case NTFS_DT_FIFO: file_info->type=GNOME_VFS_FILE_TYPE_FIFO; break;
328 case NTFS_DT_CHR: file_info->type=GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE; break;
329 case NTFS_DT_DIR: file_info->type=GNOME_VFS_FILE_TYPE_DIRECTORY; break;
330 case NTFS_DT_BLK: file_info->type=GNOME_VFS_FILE_TYPE_BLOCK_DEVICE; break;
331 case NTFS_DT_REG: file_info->type=GNOME_VFS_FILE_TYPE_REGULAR; break;
332 case NTFS_DT_LNK: file_info->type=GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK; break;
333 case NTFS_DT_SOCK: file_info->type=GNOME_VFS_FILE_TYPE_SOCKET; break;
334 /* FIXME: What is 'NTFS_DT_WHT'? */
335 default: file_info->type=GNOME_VFS_FILE_TYPE_UNKNOWN;
337 if (file_info->type!=GNOME_VFS_FILE_TYPE_UNKNOWN)
338 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE;
340 /* Detect 'file_info->size': */
341 if (file_info->type==GNOME_VFS_FILE_TYPE_REGULAR) {
344 inode=ntfs_inode_open(libntfs_directory->inode->vol,mref);
345 /* FIXME: Check failed 'inode' open. */
355 /* FIXME: Check failed 'attr' open. */
357 file_info->size=attr->data_size; /* FIXME: Is 'data_size' the right field? */
358 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_SIZE;
359 ntfs_attr_close(attr);
361 errint=ntfs_inode_close(inode);
362 /* FIXME: Check 'errint'. */
366 libntfs_directory->file_info_list=g_list_prepend(libntfs_directory->file_info_list,file_info);
368 return 0; /* continue traversal */
372 static GnomeVFSResult libntfs_gnomevfs_read_directory(GnomeVFSMethod *method,
373 GnomeVFSMethodHandle *method_handle,GnomeVFSFileInfo *file_info,GnomeVFSContext *context)
375 GnomeVFSResult errvfsresult;
376 struct libntfs_directory *libntfs_directory;
378 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
379 libntfs_directory=(struct libntfs_directory *)method_handle;
380 g_return_val_if_fail(libntfs_directory!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
381 g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
383 if (!libntfs_directory->file_info_list) {
387 pos=0; /* read from the start; incl. "." and ".." entries */
390 libntfs_directory->inode, /* dir_ni */
392 libntfs_directory, /* dirent */
393 (ntfs_filldir_t)libntfs_gnomevfs_read_directory_filldir); /* filldir */
396 return GNOME_VFS_ERROR_INTERNAL;
398 libntfs_directory->file_info_list=g_list_prepend(libntfs_directory->file_info_list,NULL); /* EOF */
399 libntfs_directory->file_info_list=g_list_reverse(libntfs_directory->file_info_list);
402 if (!libntfs_directory->file_info_list->data) {
403 g_assert(libntfs_directory->file_info_list->next==NULL);
404 /* Do not clear the list to leave us stuck at EOF - GnomeVFS behaves that way. */
405 errvfsresult=GNOME_VFS_ERROR_EOF;
408 /* Cut first list item. */
409 gnome_vfs_file_info_copy(
410 file_info, /* dest */
411 libntfs_directory->file_info_list->data); /* src */
412 gnome_vfs_file_info_unref(libntfs_directory->file_info_list->data);
413 libntfs_directory->file_info_list=g_list_delete_link(
414 libntfs_directory->file_info_list,libntfs_directory->file_info_list);
415 errvfsresult=GNOME_VFS_OK;
421 struct libntfs_file {
427 static GnomeVFSResult libntfs_open_attr(struct libntfs_file *libntfs_file)
429 g_return_val_if_fail(libntfs_file!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
430 g_return_val_if_fail(libntfs_file->inode!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
432 if (!libntfs_file->attr) {
434 libntfs_file->attr=ntfs_attr_open(
435 libntfs_file->inode, /* ni */
440 if (!libntfs_file->attr)
441 return GNOME_VFS_ERROR_BAD_FILE;
448 static GnomeVFSResult libntfs_gnomevfs_open(GnomeVFSMethod *method,
449 GnomeVFSMethodHandle **method_handle_return,GnomeVFSURI *uri,GnomeVFSOpenMode mode,GnomeVFSContext *context)
451 GnomeVFSResult errvfsresult;
454 struct libntfs_file *libntfs_file;
456 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
457 g_return_val_if_fail(method_handle_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
459 if (GNOME_VFS_OK!=(errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume,uri)))
462 if (mode & GNOME_VFS_OPEN_WRITE)
463 return GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM;
465 if (GNOME_VFS_OK!=(errvfsresult=inode_open_by_pathname(&inode,volume,uri->text)))
468 libntfs_new(libntfs_file);
469 libntfs_file->inode=inode;
470 libntfs_file->attr=NULL;
472 *method_handle_return=(GnomeVFSMethodHandle *)libntfs_file;
477 static GnomeVFSResult libntfs_gnomevfs_create(GnomeVFSMethod *method,
478 GnomeVFSMethodHandle **method_handle_return,GnomeVFSURI *uri,GnomeVFSOpenMode mode,gboolean exclusive,guint perm,
479 GnomeVFSContext *context)
481 GnomeVFSResult errvfsresult;
484 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
485 g_return_val_if_fail(method_handle_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
487 if (GNOME_VFS_OK!=(errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume,uri)))
490 return GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM;
494 static GnomeVFSResult libntfs_gnomevfs_close(GnomeVFSMethod *method,
495 GnomeVFSMethodHandle *method_handle,GnomeVFSContext *context)
497 struct libntfs_file *libntfs_file;
500 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
501 libntfs_file=(struct libntfs_file *)method_handle;
502 g_return_val_if_fail(libntfs_file!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
504 if (libntfs_file->attr) {
506 ntfs_attr_close(libntfs_file->attr);
510 errint=ntfs_inode_close(libntfs_file->inode);
513 g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
515 g_free(libntfs_file);
521 static GnomeVFSResult libntfs_gnomevfs_read(GnomeVFSMethod *method,GnomeVFSMethodHandle *method_handle,
522 gpointer buffer,GnomeVFSFileSize num_bytes,GnomeVFSFileSize *bytes_read_return,GnomeVFSContext *context)
524 GnomeVFSResult errvfsresult;
525 struct libntfs_file *libntfs_file;
528 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
529 libntfs_file=(struct libntfs_file *)method_handle;
530 g_return_val_if_fail(libntfs_file!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
531 g_return_val_if_fail(buffer!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
532 g_return_val_if_fail(bytes_read_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
534 if (GNOME_VFS_OK!=(errvfsresult=libntfs_open_attr(libntfs_file)))
538 g_assert((GnomeVFSFileSize)count_s64==num_bytes);
540 got=ntfs_attr_pread(libntfs_file->attr,libntfs_file->pos,count_s64,buffer);
543 return GNOME_VFS_ERROR_IO;
545 libntfs_file->pos+=got;
546 *bytes_read_return=got;
547 g_assert((s64)*bytes_read_return==got);
553 static GnomeVFSResult libntfs_gnomevfs_seek(GnomeVFSMethod *method,
554 GnomeVFSMethodHandle *method_handle,GnomeVFSSeekPosition whence,GnomeVFSFileOffset offset,GnomeVFSContext *context)
556 GnomeVFSResult errvfsresult;
557 struct libntfs_file *libntfs_file;
559 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
560 libntfs_file=(struct libntfs_file *)method_handle;
561 g_return_val_if_fail(libntfs_file!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
563 if (GNOME_VFS_OK!=(errvfsresult=libntfs_open_attr(libntfs_file)))
567 case GNOME_VFS_SEEK_START:
568 libntfs_file->pos=offset;
570 case GNOME_VFS_SEEK_CURRENT:
571 libntfs_file->pos+=offset;
573 case GNOME_VFS_SEEK_END:
574 g_return_val_if_reached(GNOME_VFS_ERROR_BAD_PARAMETERS); /* FIXME: NOT IMPLEMENTED YET */
575 default: g_assert_not_reached();
581 static GnomeVFSResult libntfs_gnomevfs_tell(GnomeVFSMethod *method,
582 GnomeVFSMethodHandle *method_handle,GnomeVFSFileOffset *offset_return)
584 GnomeVFSResult errvfsresult;
585 struct libntfs_file *libntfs_file;
587 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
588 libntfs_file=(struct libntfs_file *)method_handle;
589 g_return_val_if_fail(libntfs_file!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
590 g_return_val_if_fail(offset_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
592 if (GNOME_VFS_OK!=(errvfsresult=libntfs_open_attr(libntfs_file)))
595 *offset_return=libntfs_file->pos;
596 g_assert(*offset_return==libntfs_file->pos);
602 static gboolean libntfs_gnomevfs_is_local(GnomeVFSMethod *method,const GnomeVFSURI *uri)
604 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
605 g_return_val_if_fail(uri!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
607 return gnome_vfs_uri_is_local(uri->parent);
611 GnomeVFSResult libntfs_gnomevfs_get_file_info_from_handle(GnomeVFSMethod *method,
612 GnomeVFSMethodHandle *method_handle,GnomeVFSFileInfo *file_info,GnomeVFSFileInfoOptions options,GnomeVFSContext *context)
614 GnomeVFSResult errvfsresult;
615 struct libntfs_file *libntfs_file;
617 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
618 libntfs_file=(struct libntfs_file *)method_handle;
619 g_return_val_if_fail(libntfs_file!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
620 g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
621 /* handle 'options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE'? */
623 file_info->valid_fields=0;
624 file_info->name=NULL; /* FIXME: It is complicated to read filename of open 'ntfs_inode'. */
626 if (GNOME_VFS_OK!=(errvfsresult=libntfs_open_attr(libntfs_file))) {
627 /* Assume we are directory: */
628 file_info->type=GNOME_VFS_FILE_TYPE_DIRECTORY;
629 /* Do not: file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE;
630 * as gnome-vfs-xfer.c/copy_items() does not check 'GNOME_VFS_FILE_INFO_FIELDS_TYPE'
631 * and we are just bluffing we know it.
636 file_info->size=libntfs_file->attr->data_size; /* FIXME: Is 'data_size' the right field? */
637 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_SIZE;
639 /* FIXME: We do not really know the type of 'libntfs_file'
640 * but gnome-vfs-xfer.c/copy_items() requires 'GNOME_VFS_FILE_TYPE_REGULAR'
643 file_info->type=GNOME_VFS_FILE_TYPE_REGULAR;
644 /* Do not: file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE;
645 * as gnome-vfs-xfer.c/copy_items() does not check 'GNOME_VFS_FILE_INFO_FIELDS_TYPE'
646 * and we are just bluffing we know it.
653 static GnomeVFSResult libntfs_gnomevfs_get_file_info(GnomeVFSMethod *method,
654 GnomeVFSURI *uri,GnomeVFSFileInfo *file_info,GnomeVFSFileInfoOptions options,GnomeVFSContext *context)
656 GnomeVFSResult errvfsresult;
657 GnomeVFSMethodHandle *method_handle;
659 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
660 g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
661 /* handle 'options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE'? */
663 if (GNOME_VFS_OK!=(errvfsresult=libntfs_gnomevfs_open(method,&method_handle,uri,GNOME_VFS_OPEN_READ,context)))
665 if (GNOME_VFS_OK!=(errvfsresult=libntfs_gnomevfs_get_file_info_from_handle(method,method_handle,file_info,options,context)))
667 if (GNOME_VFS_OK!=(errvfsresult=libntfs_gnomevfs_close(method,method_handle,context)))
674 GnomeVFSResult libntfs_gnomevfs_check_same_fs(GnomeVFSMethod *method,
675 GnomeVFSURI *a,GnomeVFSURI *b,gboolean *same_fs_return,GnomeVFSContext *context)
677 ntfs_volume *volume_a;
678 ntfs_volume *volume_b;
679 GnomeVFSResult errvfsresult;
681 g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
682 g_return_val_if_fail(same_fs_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
684 errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume_a,a);
685 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
687 errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume_b,b);
688 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
690 *same_fs_return=(volume_a==volume_b);
697 * libntfs_gnomevfs_init:
699 * Returns: Initialized structure of #GnomeVFSMethod with static methods of libntfs-gnomevfs.
701 GnomeVFSMethod *libntfs_gnomevfs_method_init(const gchar *method_name,const gchar *args)
703 struct method_name_info *method_name_info;
705 g_return_val_if_fail(method_name!=NULL,NULL);
706 /* 'args' may be NULL if not supplied. */
708 method_name_hash_init();
710 G_LOCK(method_name_hash);
711 method_name_info=g_hash_table_lookup(method_name_hash,method_name);
712 if (method_name_info && strcmp(method_name_info->args,args))
713 method_name_info=NULL;
714 G_UNLOCK(method_name_hash);
715 if (!method_name_info) {
716 libntfs_new(method_name_info);
717 method_name_info->args=g_strdup(args);
718 G_LOCK(method_name_hash);
719 g_hash_table_replace(method_name_hash,g_strdup(method_name),method_name_info);
720 G_UNLOCK(method_name_hash);
723 G_LOCK(GnomeVFSMethod_static);
724 LIBNTFS_MEMZERO(&GnomeVFSMethod_static);
725 GnomeVFSMethod_static.method_table_size=sizeof(GnomeVFSMethod_static);
726 GnomeVFSMethod_static.open =libntfs_gnomevfs_open; /* mandatory */
727 GnomeVFSMethod_static.create =libntfs_gnomevfs_create; /* mandatory */
728 GnomeVFSMethod_static.close =libntfs_gnomevfs_close;
729 GnomeVFSMethod_static.read =libntfs_gnomevfs_read;
730 GnomeVFSMethod_static.seek =libntfs_gnomevfs_seek;
731 GnomeVFSMethod_static.tell =libntfs_gnomevfs_tell;
732 GnomeVFSMethod_static.open_directory =libntfs_gnomevfs_open_directory;
733 GnomeVFSMethod_static.close_directory =libntfs_gnomevfs_close_directory;
734 GnomeVFSMethod_static.read_directory =libntfs_gnomevfs_read_directory;
735 GnomeVFSMethod_static.get_file_info =libntfs_gnomevfs_get_file_info; /* mandatory */
736 GnomeVFSMethod_static.get_file_info_from_handle=libntfs_gnomevfs_get_file_info_from_handle;
737 GnomeVFSMethod_static.is_local =libntfs_gnomevfs_is_local; /* mandatory */
738 GnomeVFSMethod_static.check_same_fs =libntfs_gnomevfs_check_same_fs;
739 /* TODO: GnomeVFSMethodFindDirectoryFunc find_directory; */
740 /* TODO: GnomeVFSMethodFileControlFunc file_control; */
741 /* R/W: GnomeVFSMethodCreateSymbolicLinkFunc create_symbolic_link; */
742 /* R/W: GnomeVFSMethodMonitorAddFunc monitor_add; */
743 /* R/W: GnomeVFSMethodMonitorCancelFunc monitor_cancel; */
744 /* R/W: GnomeVFSMethod_static.write; */
745 /* R/W: GnomeVFSMethod_static.truncate_handle; */
746 /* R/W: GnomeVFSMethod_static.make_directory; */
747 /* R/W: GnomeVFSMethod_static.remove_directory; */
748 /* R/W: GnomeVFSMethod_static.move; */
749 /* R/W: GnomeVFSMethod_static.unlink; */
750 /* R/W: GnomeVFSMethod_static.set_file_info; */
751 /* R/W: GnomeVFSMethod_static.truncate; */
752 G_UNLOCK(GnomeVFSMethod_static);
754 return &GnomeVFSMethod_static;
759 * libntfs_gnomevfs_method_shutdown:
761 * Shutdowns libntfs-gnomevfs successfuly flushing all caches.
763 * Sad note about gnome-vfs-2.1.5 is that it never calls this function. :-)
765 void libntfs_gnomevfs_method_shutdown(void)
767 uri_parent_string_hash_init();
768 G_LOCK(uri_parent_string_hash);
769 g_hash_table_destroy(uri_parent_string_hash);
770 uri_parent_string_hash=NULL;
771 G_UNLOCK(uri_parent_string_hash);
773 method_name_hash_init();
774 G_LOCK(method_name_hash);
775 g_hash_table_destroy(method_name_hash);
776 method_name_hash=NULL;
777 G_UNLOCK(method_name_hash);