xref: /onnv-gate/usr/src/lib/libntfs/common/libntfs/gnome-vfs-method.c (revision 10214:1f70f0c2183c)
19663SMark.Logan@Sun.COM /*
29663SMark.Logan@Sun.COM  * gnome-vfs-method.c - Gnome-VFS init/shutdown implementation of interface to
39663SMark.Logan@Sun.COM  *			libntfs. Part of the Linux-NTFS project.
49663SMark.Logan@Sun.COM  *
59663SMark.Logan@Sun.COM  * Copyright (c) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
69663SMark.Logan@Sun.COM  * Copyright (c) 2003-2006 Anton Altaparmakov
79663SMark.Logan@Sun.COM  *
89663SMark.Logan@Sun.COM  * This program/include file is free software; you can redistribute it and/or
99663SMark.Logan@Sun.COM  * modify it under the terms of the GNU General Public License as published
109663SMark.Logan@Sun.COM  * by the Free Software Foundation; either version 2 of the License, or
119663SMark.Logan@Sun.COM  * (at your option) any later version.
129663SMark.Logan@Sun.COM  *
139663SMark.Logan@Sun.COM  * This program/include file is distributed in the hope that it will be
149663SMark.Logan@Sun.COM  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
159663SMark.Logan@Sun.COM  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
169663SMark.Logan@Sun.COM  * GNU General Public License for more details.
179663SMark.Logan@Sun.COM  *
189663SMark.Logan@Sun.COM  * You should have received a copy of the GNU General Public License
199663SMark.Logan@Sun.COM  * along with this program (in the main directory of the Linux-NTFS
209663SMark.Logan@Sun.COM  * distribution in the file COPYING); if not, write to the Free Software
219663SMark.Logan@Sun.COM  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
229663SMark.Logan@Sun.COM  */
239663SMark.Logan@Sun.COM 
249663SMark.Logan@Sun.COM #include "config.h"
259663SMark.Logan@Sun.COM 
269663SMark.Logan@Sun.COM #undef FALSE
279663SMark.Logan@Sun.COM #undef TRUE
289663SMark.Logan@Sun.COM #include "types.h"		/* for 'FALSE'/'TRUE' libntfs definition */
299663SMark.Logan@Sun.COM #define FALSE FALSE
309663SMark.Logan@Sun.COM #define TRUE TRUE
319663SMark.Logan@Sun.COM 
329663SMark.Logan@Sun.COM #include "gnome-vfs-method.h"	/* self */
339663SMark.Logan@Sun.COM #include <libgnomevfs/gnome-vfs-method.h>
349663SMark.Logan@Sun.COM #include <glib/gmessages.h>
359663SMark.Logan@Sun.COM #include "gnome-vfs-module.h"
369663SMark.Logan@Sun.COM #include <glib/ghash.h>
379663SMark.Logan@Sun.COM #ifdef HAVE_STRING_H
389663SMark.Logan@Sun.COM #include <string.h>
399663SMark.Logan@Sun.COM #endif
409663SMark.Logan@Sun.COM #include <libgnomevfs/gnome-vfs-utils.h>
419663SMark.Logan@Sun.COM 
42*10214SMark.Logan@Sun.COM #include "compat.h"
439663SMark.Logan@Sun.COM #include "volume.h"
449663SMark.Logan@Sun.COM #include "dir.h"
459663SMark.Logan@Sun.COM 
469663SMark.Logan@Sun.COM static GnomeVFSMethod GnomeVFSMethod_static;
479663SMark.Logan@Sun.COM G_LOCK_DEFINE_STATIC(GnomeVFSMethod_static);
489663SMark.Logan@Sun.COM 
499663SMark.Logan@Sun.COM /* map: (gchar *)method_name -> (struct method_name_info *) */
509663SMark.Logan@Sun.COM static GHashTable *method_name_hash;
519663SMark.Logan@Sun.COM G_LOCK_DEFINE_STATIC(method_name_hash);
529663SMark.Logan@Sun.COM 
539663SMark.Logan@Sun.COM #ifdef __sun
549663SMark.Logan@Sun.COM G_LOCK_DEFINE(libntfs);
559663SMark.Logan@Sun.COM #endif
569663SMark.Logan@Sun.COM 
579663SMark.Logan@Sun.COM struct method_name_info {
589663SMark.Logan@Sun.COM 	gchar *args;
599663SMark.Logan@Sun.COM };
609663SMark.Logan@Sun.COM 
method_name_hash_key_destroy_func(gchar * key)619663SMark.Logan@Sun.COM static void method_name_hash_key_destroy_func(gchar *key)
629663SMark.Logan@Sun.COM {
639663SMark.Logan@Sun.COM 	g_return_if_fail(key != NULL);
649663SMark.Logan@Sun.COM 
659663SMark.Logan@Sun.COM 	g_free(key);
669663SMark.Logan@Sun.COM }
679663SMark.Logan@Sun.COM 
method_name_hash_value_destroy_func(struct method_name_info * value)689663SMark.Logan@Sun.COM static void method_name_hash_value_destroy_func(struct method_name_info *value)
699663SMark.Logan@Sun.COM {
709663SMark.Logan@Sun.COM 	g_return_if_fail(value != NULL);
719663SMark.Logan@Sun.COM 
729663SMark.Logan@Sun.COM 	g_free(value->args);
739663SMark.Logan@Sun.COM 	g_free(value);
749663SMark.Logan@Sun.COM }
759663SMark.Logan@Sun.COM 
method_name_hash_init(void)769663SMark.Logan@Sun.COM static void method_name_hash_init(void)
779663SMark.Logan@Sun.COM {
789663SMark.Logan@Sun.COM 	G_LOCK(method_name_hash);
799663SMark.Logan@Sun.COM 	if (!method_name_hash) {
809663SMark.Logan@Sun.COM 		method_name_hash = g_hash_table_new_full(
819663SMark.Logan@Sun.COM 				g_str_hash,	/* hash_func */
829663SMark.Logan@Sun.COM 				g_str_equal,	/* key_equal_func */
839663SMark.Logan@Sun.COM 				(GDestroyNotify) method_name_hash_key_destroy_func,	/* key_destroy_func */
849663SMark.Logan@Sun.COM 				(GDestroyNotify) method_name_hash_value_destroy_func);	/* value_destroy_func */
859663SMark.Logan@Sun.COM 	}
869663SMark.Logan@Sun.COM 	G_UNLOCK(method_name_hash);
879663SMark.Logan@Sun.COM }
889663SMark.Logan@Sun.COM 
899663SMark.Logan@Sun.COM /*
909663SMark.Logan@Sun.COM  * map: (gchar *)uri_parent_string "method_name:uri_parent" -> (ntfs_volume *)
919663SMark.Logan@Sun.COM  */
929663SMark.Logan@Sun.COM static GHashTable *uri_parent_string_hash;
939663SMark.Logan@Sun.COM G_LOCK_DEFINE_STATIC(uri_parent_string_hash);
949663SMark.Logan@Sun.COM 
uri_parent_string_hash_key_destroy_func(gchar * key)959663SMark.Logan@Sun.COM static void uri_parent_string_hash_key_destroy_func(gchar *key)
969663SMark.Logan@Sun.COM {
979663SMark.Logan@Sun.COM 	g_return_if_fail(key != NULL);
989663SMark.Logan@Sun.COM 
999663SMark.Logan@Sun.COM 	g_free(key);
1009663SMark.Logan@Sun.COM }
1019663SMark.Logan@Sun.COM 
uri_parent_string_hash_value_destroy_func(ntfs_volume * value)1029663SMark.Logan@Sun.COM static void uri_parent_string_hash_value_destroy_func(ntfs_volume *value)
1039663SMark.Logan@Sun.COM {
1049663SMark.Logan@Sun.COM 	g_return_if_fail(value != NULL);
1059663SMark.Logan@Sun.COM 
1069663SMark.Logan@Sun.COM 	ntfs_umount(	/* errors ignored */
1079663SMark.Logan@Sun.COM 			value,	/* vol */
1089663SMark.Logan@Sun.COM 			TRUE);	/* force; possibly loose modifications */
1099663SMark.Logan@Sun.COM }
1109663SMark.Logan@Sun.COM 
uri_parent_string_hash_init(void)1119663SMark.Logan@Sun.COM static void uri_parent_string_hash_init(void)
1129663SMark.Logan@Sun.COM {
1139663SMark.Logan@Sun.COM 	G_LOCK(uri_parent_string_hash);
1149663SMark.Logan@Sun.COM 	if (!uri_parent_string_hash) {
1159663SMark.Logan@Sun.COM 		uri_parent_string_hash = g_hash_table_new_full(
1169663SMark.Logan@Sun.COM 				g_str_hash,	/* hash_func */
1179663SMark.Logan@Sun.COM 				g_str_equal,	/* key_equal_func */
1189663SMark.Logan@Sun.COM 				(GDestroyNotify) uri_parent_string_hash_key_destroy_func,	/* key_destroy_func */
1199663SMark.Logan@Sun.COM 				(GDestroyNotify) uri_parent_string_hash_value_destroy_func);	/* value_destroy_func */
1209663SMark.Logan@Sun.COM 	}
1219663SMark.Logan@Sun.COM 	G_UNLOCK(uri_parent_string_hash);
1229663SMark.Logan@Sun.COM }
1239663SMark.Logan@Sun.COM 
libntfs_gnomevfs_uri_parent_init(ntfs_volume ** volume_return,GnomeVFSURI * uri)1249663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_uri_parent_init(
1259663SMark.Logan@Sun.COM 		ntfs_volume **volume_return, GnomeVFSURI *uri)
1269663SMark.Logan@Sun.COM {
1279663SMark.Logan@Sun.COM 	gchar *uri_parent_string;
1289663SMark.Logan@Sun.COM 	gchar *uri_parent_string_parent;
1299663SMark.Logan@Sun.COM 	ntfs_volume *volume;
1309663SMark.Logan@Sun.COM 
1319663SMark.Logan@Sun.COM 	g_return_val_if_fail(uri != NULL, GNOME_VFS_ERROR_INVALID_URI);
1329663SMark.Logan@Sun.COM 	g_return_val_if_fail(volume_return != NULL,
1339663SMark.Logan@Sun.COM 			     GNOME_VFS_ERROR_BAD_PARAMETERS);
1349663SMark.Logan@Sun.COM 
1359663SMark.Logan@Sun.COM 	uri_parent_string_hash_init();
1369663SMark.Logan@Sun.COM 
1379663SMark.Logan@Sun.COM 	if (!uri->parent)
1389663SMark.Logan@Sun.COM 		return GNOME_VFS_ERROR_INVALID_URI;
1399663SMark.Logan@Sun.COM 	if (!uri->text)		/* not needed here but we don't permit non-specific fs-image reference */
1409663SMark.Logan@Sun.COM 		return GNOME_VFS_ERROR_INVALID_URI;
1419663SMark.Logan@Sun.COM 	uri_parent_string_parent = gnome_vfs_uri_to_string(uri->parent,
1429663SMark.Logan@Sun.COM 			GNOME_VFS_URI_HIDE_NONE);
1439663SMark.Logan@Sun.COM 	g_assert(uri_parent_string_parent != NULL);
1449663SMark.Logan@Sun.COM 
1459663SMark.Logan@Sun.COM 	uri_parent_string = g_strdup_printf("%s:%s", uri->method_string,
1469663SMark.Logan@Sun.COM 			uri_parent_string_parent);
1479663SMark.Logan@Sun.COM 	g_assert(uri_parent_string != NULL);
1489663SMark.Logan@Sun.COM 
1499663SMark.Logan@Sun.COM 	G_LOCK(uri_parent_string_hash);
1509663SMark.Logan@Sun.COM 	volume = g_hash_table_lookup(uri_parent_string_hash, uri_parent_string);
1519663SMark.Logan@Sun.COM 	G_UNLOCK(uri_parent_string_hash);
1529663SMark.Logan@Sun.COM 	if (!volume) {
1539663SMark.Logan@Sun.COM 		struct method_name_info *method_name_info;
1549663SMark.Logan@Sun.COM 
1559663SMark.Logan@Sun.COM 		G_LOCK(method_name_hash);
1569663SMark.Logan@Sun.COM 		method_name_info = g_hash_table_lookup(method_name_hash,
1579663SMark.Logan@Sun.COM 				uri->method_string);
1589663SMark.Logan@Sun.COM 		G_UNLOCK(method_name_hash);
1599663SMark.Logan@Sun.COM 		if (!method_name_info) {
1609663SMark.Logan@Sun.COM 			/* should not happend */
1619663SMark.Logan@Sun.COM 			g_return_val_if_reached(GNOME_VFS_ERROR_INVALID_URI);
1629663SMark.Logan@Sun.COM 		}
1639663SMark.Logan@Sun.COM 
1649663SMark.Logan@Sun.COM 		/* TODO: Generic GnomeVFS filter. */
1659663SMark.Logan@Sun.COM 		if (strcmp(uri->parent->method_string, "file")) {
1669663SMark.Logan@Sun.COM 			g_free(uri_parent_string);
1679663SMark.Logan@Sun.COM 			return GNOME_VFS_ERROR_INVALID_URI;
1689663SMark.Logan@Sun.COM 		}
1699663SMark.Logan@Sun.COM 
1709663SMark.Logan@Sun.COM 		if (!(volume = ntfs_mount(uri->parent->text,
1719663SMark.Logan@Sun.COM 				NTFS_MNT_RDONLY))) {
1729663SMark.Logan@Sun.COM 			g_free(uri_parent_string);
1739663SMark.Logan@Sun.COM 			return GNOME_VFS_ERROR_WRONG_FORMAT;
1749663SMark.Logan@Sun.COM 		}
1759663SMark.Logan@Sun.COM 
1769663SMark.Logan@Sun.COM 		G_LOCK(uri_parent_string_hash);
1779663SMark.Logan@Sun.COM 		g_hash_table_insert(uri_parent_string_hash,
1789663SMark.Logan@Sun.COM 				g_strdup(uri_parent_string), volume);
1799663SMark.Logan@Sun.COM 		G_UNLOCK(uri_parent_string_hash);
1809663SMark.Logan@Sun.COM 	}
1819663SMark.Logan@Sun.COM 	g_free(uri_parent_string);
1829663SMark.Logan@Sun.COM 
1839663SMark.Logan@Sun.COM 	*volume_return = volume;
1849663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
1859663SMark.Logan@Sun.COM }
1869663SMark.Logan@Sun.COM 
inode_open_by_pathname(ntfs_inode ** inode_return,ntfs_volume * volume,const gchar * pathname)1879663SMark.Logan@Sun.COM static GnomeVFSResult inode_open_by_pathname(ntfs_inode **inode_return,
1889663SMark.Logan@Sun.COM 		ntfs_volume *volume, const gchar *pathname)
1899663SMark.Logan@Sun.COM {
1909663SMark.Logan@Sun.COM 	MFT_REF mref;
1919663SMark.Logan@Sun.COM 	ntfs_inode *inode;
1929663SMark.Logan@Sun.COM 	gchar *pathname_parse, *pathname_next;
1939663SMark.Logan@Sun.COM 	int errint;
1949663SMark.Logan@Sun.COM 
1959663SMark.Logan@Sun.COM 	g_return_val_if_fail(inode_return != NULL,
1969663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
1979663SMark.Logan@Sun.COM 	g_return_val_if_fail(volume != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
1989663SMark.Logan@Sun.COM 	g_return_val_if_fail(pathname != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
1999663SMark.Logan@Sun.COM 
2009663SMark.Logan@Sun.COM 	pathname = g_path_skip_root(pathname);
2019663SMark.Logan@Sun.COM 	pathname_parse = g_alloca(strlen(pathname) + 1);
2029663SMark.Logan@Sun.COM 	strcpy(pathname_parse, pathname);
2039663SMark.Logan@Sun.COM 	mref = FILE_root;
2049663SMark.Logan@Sun.COM 	for (;;) {
2059663SMark.Logan@Sun.COM 		ntfschar *pathname_parse_ucs2;
2069663SMark.Logan@Sun.COM 		gchar *pathname_parse_unescaped;
2079663SMark.Logan@Sun.COM 		int i;
2089663SMark.Logan@Sun.COM 
2099663SMark.Logan@Sun.COM 		G_LOCK(libntfs);
2109663SMark.Logan@Sun.COM 		inode = ntfs_inode_open(volume, mref);
2119663SMark.Logan@Sun.COM 		G_UNLOCK(libntfs);
2129663SMark.Logan@Sun.COM 		if (!inode)
2139663SMark.Logan@Sun.COM 			return GNOME_VFS_ERROR_NOT_FOUND;
2149663SMark.Logan@Sun.COM 		if (!*pathname_parse) {
2159663SMark.Logan@Sun.COM 			*inode_return = inode;
2169663SMark.Logan@Sun.COM 			return GNOME_VFS_OK;
2179663SMark.Logan@Sun.COM 		}
2189663SMark.Logan@Sun.COM 		for (pathname_next = pathname_parse; *pathname_next &&
2199663SMark.Logan@Sun.COM 		     *pathname_next != G_DIR_SEPARATOR; pathname_next++) ;
2209663SMark.Logan@Sun.COM 		if (*pathname_next) {
2219663SMark.Logan@Sun.COM 			/* terminate current path element */
2229663SMark.Logan@Sun.COM 			*pathname_next++ = 0;
2239663SMark.Logan@Sun.COM 		}
2249663SMark.Logan@Sun.COM 		while (*pathname_next == G_DIR_SEPARATOR)
2259663SMark.Logan@Sun.COM 			pathname_next++;
2269663SMark.Logan@Sun.COM 		/* FIXME: Is 'pathname' utf8? */
2279663SMark.Logan@Sun.COM 		pathname_parse_unescaped = gnome_vfs_unescape_string(
2289663SMark.Logan@Sun.COM 				pathname_parse, NULL);	/* illegal_characters */
2299663SMark.Logan@Sun.COM #ifdef __sun
2309663SMark.Logan@Sun.COM 		pathname_parse_ucs2 = g_malloc(strlen(pathname_parse_unescaped) + 1);
2319663SMark.Logan@Sun.COM #else /* !__sun */
2329663SMark.Logan@Sun.COM 		libntfs_newn(pathname_parse_ucs2,
2339663SMark.Logan@Sun.COM 				strlen(pathname_parse_unescaped) + 1);
2349663SMark.Logan@Sun.COM #endif /* __sun */
2359663SMark.Logan@Sun.COM 		for (i = 0; pathname_parse_unescaped[i]; i++)
2369663SMark.Logan@Sun.COM 			pathname_parse_ucs2[i] = cpu_to_le16(
2379663SMark.Logan@Sun.COM 					pathname_parse_unescaped[i]);
2389663SMark.Logan@Sun.COM 		pathname_parse_ucs2[i] = 0;
2399663SMark.Logan@Sun.COM 		g_free(pathname_parse_unescaped);
2409663SMark.Logan@Sun.COM 		G_LOCK(libntfs);
2419663SMark.Logan@Sun.COM 		mref = ntfs_inode_lookup_by_name(inode, pathname_parse_ucs2, i);
2429663SMark.Logan@Sun.COM 		G_UNLOCK(libntfs);
2439663SMark.Logan@Sun.COM 		g_free(pathname_parse_ucs2);
2449663SMark.Logan@Sun.COM 		if ((MFT_REF)-1 == mref)
2459663SMark.Logan@Sun.COM 			return GNOME_VFS_ERROR_NOT_FOUND;
2469663SMark.Logan@Sun.COM 		G_LOCK(libntfs);
2479663SMark.Logan@Sun.COM 		errint = ntfs_inode_close(inode);
2489663SMark.Logan@Sun.COM 		G_UNLOCK(libntfs);
2499663SMark.Logan@Sun.COM 		if (errint)
2509663SMark.Logan@Sun.COM 			g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
2519663SMark.Logan@Sun.COM 		pathname_parse = pathname_next;
2529663SMark.Logan@Sun.COM 	}
2539663SMark.Logan@Sun.COM 	/* NOTREACHED */
2549663SMark.Logan@Sun.COM }
2559663SMark.Logan@Sun.COM 
2569663SMark.Logan@Sun.COM struct libntfs_directory {
2579663SMark.Logan@Sun.COM 	ntfs_inode *inode;
2589663SMark.Logan@Sun.COM 	GList *file_info_list;	/* of (GnomeVFSFileInfo *); last item has ->data == NULL */
2599663SMark.Logan@Sun.COM };
2609663SMark.Logan@Sun.COM 
libntfs_gnomevfs_open_directory(GnomeVFSMethod * method,GnomeVFSMethodHandle ** method_handle,GnomeVFSURI * uri,GnomeVFSFileInfoOptions options,GnomeVFSContext * context)2619663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_open_directory(GnomeVFSMethod *method,
2629663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle **method_handle, GnomeVFSURI *uri,
2639663SMark.Logan@Sun.COM 		GnomeVFSFileInfoOptions options __attribute__((unused)),
2649663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
2659663SMark.Logan@Sun.COM {
2669663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
2679663SMark.Logan@Sun.COM 	ntfs_volume *volume;
2689663SMark.Logan@Sun.COM 	ntfs_inode *inode;
2699663SMark.Logan@Sun.COM 	struct libntfs_directory *libntfs_directory;
2709663SMark.Logan@Sun.COM 
2719663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
2729663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
2739663SMark.Logan@Sun.COM 	g_return_val_if_fail(method_handle != NULL,
2749663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
2759663SMark.Logan@Sun.COM 
2769663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
2779663SMark.Logan@Sun.COM 			libntfs_gnomevfs_uri_parent_init(&volume, uri)))
2789663SMark.Logan@Sun.COM 		return errvfsresult;
2799663SMark.Logan@Sun.COM 
2809663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult = inode_open_by_pathname(&inode,
2819663SMark.Logan@Sun.COM 			volume, uri->text)))
2829663SMark.Logan@Sun.COM 		return errvfsresult;
2839663SMark.Logan@Sun.COM 
2849663SMark.Logan@Sun.COM #ifdef __sun
2859663SMark.Logan@Sun.COM 	libntfs_directory = g_new(struct libntfs_directory, 1);
2869663SMark.Logan@Sun.COM #else /* !__sun */
2879663SMark.Logan@Sun.COM 	libntfs_new(libntfs_directory);
2889663SMark.Logan@Sun.COM #endif /* __sun */
2899663SMark.Logan@Sun.COM 
2909663SMark.Logan@Sun.COM 	libntfs_directory->inode = inode;
2919663SMark.Logan@Sun.COM 	libntfs_directory->file_info_list = NULL;
2929663SMark.Logan@Sun.COM 
2939663SMark.Logan@Sun.COM 	*method_handle = (GnomeVFSMethodHandle *)libntfs_directory;
2949663SMark.Logan@Sun.COM 	return errvfsresult;
2959663SMark.Logan@Sun.COM }
2969663SMark.Logan@Sun.COM 
libntfs_gnomevfs_close_directory(GnomeVFSMethod * method,GnomeVFSMethodHandle * method_handle,GnomeVFSContext * context)2979663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_close_directory(GnomeVFSMethod *method,
2989663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle *method_handle,
2999663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
3009663SMark.Logan@Sun.COM {
3019663SMark.Logan@Sun.COM 	struct libntfs_directory *libntfs_directory;
3029663SMark.Logan@Sun.COM 	int errint;
3039663SMark.Logan@Sun.COM 
3049663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
3059663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
3069663SMark.Logan@Sun.COM 	libntfs_directory = (struct libntfs_directory *)method_handle;
3079663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_directory != NULL,
3089663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
3099663SMark.Logan@Sun.COM 
3109663SMark.Logan@Sun.COM 	G_LOCK(libntfs);
3119663SMark.Logan@Sun.COM 	errint = ntfs_inode_close(libntfs_directory->inode);
3129663SMark.Logan@Sun.COM 	G_UNLOCK(libntfs);
3139663SMark.Logan@Sun.COM 	if (errint)
3149663SMark.Logan@Sun.COM 		g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
3159663SMark.Logan@Sun.COM 
3169663SMark.Logan@Sun.COM 	if (libntfs_directory->file_info_list) {
3179663SMark.Logan@Sun.COM 		GList *last_l;
3189663SMark.Logan@Sun.COM 
3199663SMark.Logan@Sun.COM 		/*
3209663SMark.Logan@Sun.COM 		 * Prevent gnome_vfs_file_info_list_free() and its
3219663SMark.Logan@Sun.COM 		 * gnome_vfs_file_info_unref() on the last 'file_info_list'
3229663SMark.Logan@Sun.COM 		 * items as it is EOF with NULL '->data'.
3239663SMark.Logan@Sun.COM 		 */
3249663SMark.Logan@Sun.COM 		last_l = g_list_last(libntfs_directory->file_info_list);
3259663SMark.Logan@Sun.COM 		g_assert(last_l->data == NULL);
3269663SMark.Logan@Sun.COM 		libntfs_directory->file_info_list = g_list_delete_link(
3279663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list, last_l);
3289663SMark.Logan@Sun.COM 		gnome_vfs_file_info_list_free(
3299663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list);
3309663SMark.Logan@Sun.COM 	}
3319663SMark.Logan@Sun.COM 
3329663SMark.Logan@Sun.COM 	g_free(libntfs_directory);
3339663SMark.Logan@Sun.COM 
3349663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
3359663SMark.Logan@Sun.COM }
3369663SMark.Logan@Sun.COM 
libntfs_ntfscharo_utf8(const ntfschar * name,const int name_len)3379663SMark.Logan@Sun.COM static gchar *libntfs_ntfscharo_utf8(const ntfschar *name, const int name_len)
3389663SMark.Logan@Sun.COM {
3399663SMark.Logan@Sun.COM 	GString *gstring;
3409663SMark.Logan@Sun.COM 	int i;
3419663SMark.Logan@Sun.COM 
3429663SMark.Logan@Sun.COM 	gstring = g_string_sized_new(name_len);
3439663SMark.Logan@Sun.COM 	for (i = 0; i < name_len; i++)
3449663SMark.Logan@Sun.COM 		gstring = g_string_append_unichar(gstring,
3459663SMark.Logan@Sun.COM 				le16_to_cpu(name[i]));
3469663SMark.Logan@Sun.COM 	return g_string_free(gstring,	/* returns utf8-formatted string */
3479663SMark.Logan@Sun.COM 			FALSE);	/* free_segment */
3489663SMark.Logan@Sun.COM }
3499663SMark.Logan@Sun.COM 
3509663SMark.Logan@Sun.COM /*
3519663SMark.Logan@Sun.COM  * Do not lock 'libntfs' here as we are already locked inside ntfs_readdir().
3529663SMark.Logan@Sun.COM  */
libntfs_gnomevfs_read_directory_filldir(struct libntfs_directory * libntfs_directory,const ntfschar * name,const int name_len,const int name_type,const s64 pos,const MFT_REF mref,const unsigned dt_type)3539663SMark.Logan@Sun.COM static int libntfs_gnomevfs_read_directory_filldir(
3549663SMark.Logan@Sun.COM 		struct libntfs_directory *libntfs_directory /* dirent */,
3559663SMark.Logan@Sun.COM 		const ntfschar *name, const int name_len,
3569663SMark.Logan@Sun.COM 		const int name_type __attribute__((unused)),
3579663SMark.Logan@Sun.COM 		const s64 pos, const MFT_REF mref, const unsigned dt_type)
3589663SMark.Logan@Sun.COM {
3599663SMark.Logan@Sun.COM 	GnomeVFSFileInfo *file_info;
3609663SMark.Logan@Sun.COM 
3619663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_directory != NULL, -1);
3629663SMark.Logan@Sun.COM 	g_return_val_if_fail(name != NULL, -1);
3639663SMark.Logan@Sun.COM 	g_return_val_if_fail(name_len >= 0, -1);
3649663SMark.Logan@Sun.COM 	g_return_val_if_fail(pos >= 0, -1);
3659663SMark.Logan@Sun.COM 
3669663SMark.Logan@Sun.COM 	/* system directory */
3679663SMark.Logan@Sun.COM 	if (MREF(mref) != FILE_root && MREF(mref) < FILE_first_user)
3689663SMark.Logan@Sun.COM 		return 0;	/* continue traversal */
3699663SMark.Logan@Sun.COM 
3709663SMark.Logan@Sun.COM 	file_info = gnome_vfs_file_info_new();
3719663SMark.Logan@Sun.COM 	file_info->name = libntfs_ntfscharo_utf8(name, name_len);
3729663SMark.Logan@Sun.COM 	file_info->valid_fields = 0;
3739663SMark.Logan@Sun.COM 
3749663SMark.Logan@Sun.COM 	switch (dt_type) {
3759663SMark.Logan@Sun.COM 	case NTFS_DT_FIFO:
3769663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_FIFO;
3779663SMark.Logan@Sun.COM 		break;
3789663SMark.Logan@Sun.COM 	case NTFS_DT_CHR:
3799663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE;
3809663SMark.Logan@Sun.COM 		break;
3819663SMark.Logan@Sun.COM 	case NTFS_DT_DIR:
3829663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_DIRECTORY;
3839663SMark.Logan@Sun.COM 		break;
3849663SMark.Logan@Sun.COM 	case NTFS_DT_BLK:
3859663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_BLOCK_DEVICE;
3869663SMark.Logan@Sun.COM 		break;
3879663SMark.Logan@Sun.COM 	case NTFS_DT_REG:
3889663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
3899663SMark.Logan@Sun.COM 		break;
3909663SMark.Logan@Sun.COM 	case NTFS_DT_LNK:
3919663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK;
3929663SMark.Logan@Sun.COM 		break;
3939663SMark.Logan@Sun.COM 	case NTFS_DT_SOCK:
3949663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
3959663SMark.Logan@Sun.COM 		break;
3969663SMark.Logan@Sun.COM 		/* FIXME: What is 'NTFS_DT_WHT'? */
3979663SMark.Logan@Sun.COM 	default:
3989663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_UNKNOWN;
3999663SMark.Logan@Sun.COM 	}
4009663SMark.Logan@Sun.COM 	if (file_info->type != GNOME_VFS_FILE_TYPE_UNKNOWN)
4019663SMark.Logan@Sun.COM 		file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_TYPE;
4029663SMark.Logan@Sun.COM 
4039663SMark.Logan@Sun.COM 	/* Detect 'file_info->size': */
4049663SMark.Logan@Sun.COM 	if (file_info->type == GNOME_VFS_FILE_TYPE_REGULAR) {
4059663SMark.Logan@Sun.COM 		ntfs_inode *inode;
4069663SMark.Logan@Sun.COM 
4079663SMark.Logan@Sun.COM 		inode = ntfs_inode_open(libntfs_directory->inode->vol, mref);
4089663SMark.Logan@Sun.COM 		/* FIXME: Check failed 'inode' open. */
4099663SMark.Logan@Sun.COM 		if (inode) {
4109663SMark.Logan@Sun.COM 			ntfs_attr *attr;
4119663SMark.Logan@Sun.COM 			int errint;
4129663SMark.Logan@Sun.COM 
4139663SMark.Logan@Sun.COM 			attr = ntfs_attr_open(inode,	/* ni */
4149663SMark.Logan@Sun.COM 					AT_DATA,	/* type */
4159663SMark.Logan@Sun.COM 					AT_UNNAMED,	/* name */
4169663SMark.Logan@Sun.COM 					0);		/* name_len */
4179663SMark.Logan@Sun.COM 			/* FIXME: Check failed 'attr' open. */
4189663SMark.Logan@Sun.COM 			if (attr) {
4199663SMark.Logan@Sun.COM 				/* FIXME: Is 'data_size' the right field? */
4209663SMark.Logan@Sun.COM 				file_info->size = attr->data_size;
4219663SMark.Logan@Sun.COM 				file_info->valid_fields |=
4229663SMark.Logan@Sun.COM 						GNOME_VFS_FILE_INFO_FIELDS_SIZE;
4239663SMark.Logan@Sun.COM 				ntfs_attr_close(attr);
4249663SMark.Logan@Sun.COM 			}
4259663SMark.Logan@Sun.COM 			errint = ntfs_inode_close(inode);
4269663SMark.Logan@Sun.COM 			/* FIXME: Check 'errint'. */
4279663SMark.Logan@Sun.COM 		}
4289663SMark.Logan@Sun.COM 	}
4299663SMark.Logan@Sun.COM 
4309663SMark.Logan@Sun.COM 	libntfs_directory->file_info_list = g_list_prepend(
4319663SMark.Logan@Sun.COM 			libntfs_directory->file_info_list, file_info);
4329663SMark.Logan@Sun.COM 
4339663SMark.Logan@Sun.COM 	return 0;	/* continue traversal */
4349663SMark.Logan@Sun.COM }
4359663SMark.Logan@Sun.COM 
libntfs_gnomevfs_read_directory(GnomeVFSMethod * method,GnomeVFSMethodHandle * method_handle,GnomeVFSFileInfo * file_info,GnomeVFSContext * context)4369663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_read_directory(GnomeVFSMethod *method,
4379663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle *method_handle,
4389663SMark.Logan@Sun.COM 		GnomeVFSFileInfo *file_info,
4399663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
4409663SMark.Logan@Sun.COM {
4419663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
4429663SMark.Logan@Sun.COM 	struct libntfs_directory *libntfs_directory;
4439663SMark.Logan@Sun.COM 
4449663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
4459663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
4469663SMark.Logan@Sun.COM 	libntfs_directory = (struct libntfs_directory *)method_handle;
4479663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_directory != NULL,
4489663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
4499663SMark.Logan@Sun.COM 	g_return_val_if_fail(file_info != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
4509663SMark.Logan@Sun.COM 
4519663SMark.Logan@Sun.COM 	if (!libntfs_directory->file_info_list) {
4529663SMark.Logan@Sun.COM 		int errint;
4539663SMark.Logan@Sun.COM 		s64 pos;
4549663SMark.Logan@Sun.COM 
4559663SMark.Logan@Sun.COM 		pos = 0; /* read from the start; incl. "." and ".." entries */
4569663SMark.Logan@Sun.COM 		G_LOCK(libntfs);
4579663SMark.Logan@Sun.COM 		errint = ntfs_readdir(libntfs_directory->inode,	/* dir_ni */
4589663SMark.Logan@Sun.COM 				&pos,	/* pos */
4599663SMark.Logan@Sun.COM 				libntfs_directory,	/* dirent */
4609663SMark.Logan@Sun.COM 				(ntfs_filldir_t)libntfs_gnomevfs_read_directory_filldir);	/* filldir */
4619663SMark.Logan@Sun.COM 		G_UNLOCK(libntfs);
4629663SMark.Logan@Sun.COM 		if (errint)
4639663SMark.Logan@Sun.COM 			return GNOME_VFS_ERROR_INTERNAL;
4649663SMark.Logan@Sun.COM 
4659663SMark.Logan@Sun.COM 		libntfs_directory->file_info_list = g_list_prepend(
4669663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list, NULL); /* EOF */
4679663SMark.Logan@Sun.COM 		libntfs_directory->file_info_list = g_list_reverse(
4689663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list);
4699663SMark.Logan@Sun.COM 	}
4709663SMark.Logan@Sun.COM 
4719663SMark.Logan@Sun.COM 	if (!libntfs_directory->file_info_list->data) {
4729663SMark.Logan@Sun.COM 		g_assert(libntfs_directory->file_info_list->next == NULL);
4739663SMark.Logan@Sun.COM 		/*
4749663SMark.Logan@Sun.COM 		 * Do not clear the list to leave us stuck at EOF - GnomeVFS
4759663SMark.Logan@Sun.COM 		 * behaves that way.
4769663SMark.Logan@Sun.COM 		 */
4779663SMark.Logan@Sun.COM 		errvfsresult = GNOME_VFS_ERROR_EOF;
4789663SMark.Logan@Sun.COM 	} else {
4799663SMark.Logan@Sun.COM 		/* Cut first list item. */
4809663SMark.Logan@Sun.COM 		gnome_vfs_file_info_copy(file_info, /* dest */
4819663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list->data); /* src */
4829663SMark.Logan@Sun.COM 		gnome_vfs_file_info_unref(
4839663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list->data);
4849663SMark.Logan@Sun.COM 		libntfs_directory->file_info_list = g_list_delete_link(
4859663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list,
4869663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list);
4879663SMark.Logan@Sun.COM 		errvfsresult = GNOME_VFS_OK;
4889663SMark.Logan@Sun.COM 	}
4899663SMark.Logan@Sun.COM 	return errvfsresult;
4909663SMark.Logan@Sun.COM }
4919663SMark.Logan@Sun.COM 
4929663SMark.Logan@Sun.COM struct libntfs_file {
4939663SMark.Logan@Sun.COM 	ntfs_inode *inode;
4949663SMark.Logan@Sun.COM 	ntfs_attr *attr;
4959663SMark.Logan@Sun.COM 	s64 pos;
4969663SMark.Logan@Sun.COM };
4979663SMark.Logan@Sun.COM 
libntfs_open_attr(struct libntfs_file * libntfs_file)4989663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_open_attr(struct libntfs_file *libntfs_file)
4999663SMark.Logan@Sun.COM {
5009663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file != NULL,
5019663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
5029663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file->inode != NULL,
5039663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
5049663SMark.Logan@Sun.COM 
5059663SMark.Logan@Sun.COM 	if (!libntfs_file->attr) {
5069663SMark.Logan@Sun.COM 		G_LOCK(libntfs);
5079663SMark.Logan@Sun.COM 		libntfs_file->attr = ntfs_attr_open(
5089663SMark.Logan@Sun.COM 				libntfs_file->inode,	/* ni */
5099663SMark.Logan@Sun.COM 				AT_DATA,	/* type */
5109663SMark.Logan@Sun.COM 				AT_UNNAMED,	/* name */
5119663SMark.Logan@Sun.COM 				0);	/* name_len */
5129663SMark.Logan@Sun.COM 		G_UNLOCK(libntfs);
5139663SMark.Logan@Sun.COM 		if (!libntfs_file->attr)
5149663SMark.Logan@Sun.COM 			return GNOME_VFS_ERROR_BAD_FILE;
5159663SMark.Logan@Sun.COM 		libntfs_file->pos = 0;
5169663SMark.Logan@Sun.COM 	}
5179663SMark.Logan@Sun.COM 
5189663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
5199663SMark.Logan@Sun.COM }
5209663SMark.Logan@Sun.COM 
libntfs_gnomevfs_open(GnomeVFSMethod * method,GnomeVFSMethodHandle ** method_handle_return,GnomeVFSURI * uri,GnomeVFSOpenMode mode,GnomeVFSContext * context)5219663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_open(GnomeVFSMethod *method,
5229663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle **method_handle_return, GnomeVFSURI *uri,
5239663SMark.Logan@Sun.COM 		GnomeVFSOpenMode mode,
5249663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
5259663SMark.Logan@Sun.COM {
5269663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
5279663SMark.Logan@Sun.COM 	ntfs_volume *volume;
5289663SMark.Logan@Sun.COM 	ntfs_inode *inode;
5299663SMark.Logan@Sun.COM 	struct libntfs_file *libntfs_file;
5309663SMark.Logan@Sun.COM 
5319663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
5329663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
5339663SMark.Logan@Sun.COM 	g_return_val_if_fail(method_handle_return != NULL,
5349663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
5359663SMark.Logan@Sun.COM 
5369663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
5379663SMark.Logan@Sun.COM 			libntfs_gnomevfs_uri_parent_init(&volume, uri)))
5389663SMark.Logan@Sun.COM 		return errvfsresult;
5399663SMark.Logan@Sun.COM 
5409663SMark.Logan@Sun.COM 	if (mode & GNOME_VFS_OPEN_WRITE)
5419663SMark.Logan@Sun.COM 		return GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM;
5429663SMark.Logan@Sun.COM 
5439663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
5449663SMark.Logan@Sun.COM 			inode_open_by_pathname(&inode, volume, uri->text)))
5459663SMark.Logan@Sun.COM 		return errvfsresult;
5469663SMark.Logan@Sun.COM 
5479663SMark.Logan@Sun.COM #ifdef __sun
5489663SMark.Logan@Sun.COM 	libntfs_file = g_new(struct libntfs_file, 1);
5499663SMark.Logan@Sun.COM #else /* !__sun */
5509663SMark.Logan@Sun.COM 	libntfs_new(libntfs_file);
5519663SMark.Logan@Sun.COM #endif /* __sun */
5529663SMark.Logan@Sun.COM 
5539663SMark.Logan@Sun.COM 	libntfs_file->inode = inode;
5549663SMark.Logan@Sun.COM 	libntfs_file->attr = NULL;
5559663SMark.Logan@Sun.COM 
5569663SMark.Logan@Sun.COM 	*method_handle_return = (GnomeVFSMethodHandle *)libntfs_file;
5579663SMark.Logan@Sun.COM 	return errvfsresult;
5589663SMark.Logan@Sun.COM }
5599663SMark.Logan@Sun.COM 
libntfs_gnomevfs_create(GnomeVFSMethod * method,GnomeVFSMethodHandle ** method_handle_return,GnomeVFSURI * uri,GnomeVFSOpenMode mode,gboolean exclusive,guint perm,GnomeVFSContext * context)5609663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_create(GnomeVFSMethod *method,
5619663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle **method_handle_return, GnomeVFSURI *uri,
5629663SMark.Logan@Sun.COM 		GnomeVFSOpenMode mode __attribute__((unused)),
5639663SMark.Logan@Sun.COM 		gboolean exclusive __attribute__((unused)),
5649663SMark.Logan@Sun.COM 		guint perm __attribute__((unused)),
5659663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
5669663SMark.Logan@Sun.COM {
5679663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
5689663SMark.Logan@Sun.COM 	ntfs_volume *volume;
5699663SMark.Logan@Sun.COM 
5709663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
5719663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
5729663SMark.Logan@Sun.COM 	g_return_val_if_fail(method_handle_return != NULL,
5739663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
5749663SMark.Logan@Sun.COM 
5759663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
5769663SMark.Logan@Sun.COM 			libntfs_gnomevfs_uri_parent_init(&volume, uri)))
5779663SMark.Logan@Sun.COM 		return errvfsresult;
5789663SMark.Logan@Sun.COM 
5799663SMark.Logan@Sun.COM 	return GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM;
5809663SMark.Logan@Sun.COM }
5819663SMark.Logan@Sun.COM 
libntfs_gnomevfs_close(GnomeVFSMethod * method,GnomeVFSMethodHandle * method_handle,GnomeVFSContext * context)5829663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_close(GnomeVFSMethod *method,
5839663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle *method_handle,
5849663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
5859663SMark.Logan@Sun.COM {
5869663SMark.Logan@Sun.COM 	struct libntfs_file *libntfs_file;
5879663SMark.Logan@Sun.COM 	int errint;
5889663SMark.Logan@Sun.COM 
5899663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
5909663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
5919663SMark.Logan@Sun.COM 	libntfs_file = (struct libntfs_file *) method_handle;
5929663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file != NULL,
5939663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
5949663SMark.Logan@Sun.COM 
5959663SMark.Logan@Sun.COM 	if (libntfs_file->attr) {
5969663SMark.Logan@Sun.COM 		G_LOCK(libntfs);
5979663SMark.Logan@Sun.COM 		ntfs_attr_close(libntfs_file->attr);
5989663SMark.Logan@Sun.COM 		G_UNLOCK(libntfs);
5999663SMark.Logan@Sun.COM 	}
6009663SMark.Logan@Sun.COM 	G_LOCK(libntfs);
6019663SMark.Logan@Sun.COM 	errint = ntfs_inode_close(libntfs_file->inode);
6029663SMark.Logan@Sun.COM 	G_UNLOCK(libntfs);
6039663SMark.Logan@Sun.COM 	if (errint)
6049663SMark.Logan@Sun.COM 		g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
6059663SMark.Logan@Sun.COM 
6069663SMark.Logan@Sun.COM 	g_free(libntfs_file);
6079663SMark.Logan@Sun.COM 
6089663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
6099663SMark.Logan@Sun.COM }
6109663SMark.Logan@Sun.COM 
libntfs_gnomevfs_read(GnomeVFSMethod * method,GnomeVFSMethodHandle * method_handle,gpointer buffer,GnomeVFSFileSize num_bytes,GnomeVFSFileSize * bytes_read_return,GnomeVFSContext * context)6119663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_read(GnomeVFSMethod *method,
6129663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle *method_handle, gpointer buffer,
6139663SMark.Logan@Sun.COM 		GnomeVFSFileSize num_bytes, GnomeVFSFileSize *bytes_read_return,
6149663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
6159663SMark.Logan@Sun.COM {
6169663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
6179663SMark.Logan@Sun.COM 	struct libntfs_file *libntfs_file;
6189663SMark.Logan@Sun.COM 	s64 count_s64, got;
6199663SMark.Logan@Sun.COM 
6209663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
6219663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
6229663SMark.Logan@Sun.COM 	libntfs_file = (struct libntfs_file *)method_handle;
6239663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file != NULL,
6249663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
6259663SMark.Logan@Sun.COM 	g_return_val_if_fail(buffer != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
6269663SMark.Logan@Sun.COM 	g_return_val_if_fail(bytes_read_return != NULL,
6279663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
6289663SMark.Logan@Sun.COM 
6299663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult = libntfs_open_attr(libntfs_file)))
6309663SMark.Logan@Sun.COM 		return errvfsresult;
6319663SMark.Logan@Sun.COM 
6329663SMark.Logan@Sun.COM 	count_s64 = num_bytes;
6339663SMark.Logan@Sun.COM 	g_assert((GnomeVFSFileSize)count_s64 == num_bytes);
6349663SMark.Logan@Sun.COM 	G_LOCK(libntfs);
6359663SMark.Logan@Sun.COM 	got = ntfs_attr_pread(libntfs_file->attr, libntfs_file->pos, count_s64,
6369663SMark.Logan@Sun.COM 			buffer);
6379663SMark.Logan@Sun.COM 	G_UNLOCK(libntfs);
6389663SMark.Logan@Sun.COM 	if (got == -1)
6399663SMark.Logan@Sun.COM 		return GNOME_VFS_ERROR_IO;
6409663SMark.Logan@Sun.COM 
6419663SMark.Logan@Sun.COM 	libntfs_file->pos += got;
6429663SMark.Logan@Sun.COM 	*bytes_read_return = got;
6439663SMark.Logan@Sun.COM 	g_assert((s64)*bytes_read_return == got);
6449663SMark.Logan@Sun.COM 
6459663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
6469663SMark.Logan@Sun.COM }
6479663SMark.Logan@Sun.COM 
libntfs_gnomevfs_seek(GnomeVFSMethod * method,GnomeVFSMethodHandle * method_handle,GnomeVFSSeekPosition whence,GnomeVFSFileOffset offset,GnomeVFSContext * context)6489663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_seek(GnomeVFSMethod *method,
6499663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle *method_handle,
6509663SMark.Logan@Sun.COM 		GnomeVFSSeekPosition whence, GnomeVFSFileOffset offset,
6519663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
6529663SMark.Logan@Sun.COM {
6539663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
6549663SMark.Logan@Sun.COM 	struct libntfs_file *libntfs_file;
6559663SMark.Logan@Sun.COM 
6569663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
6579663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
6589663SMark.Logan@Sun.COM 	libntfs_file = (struct libntfs_file *)method_handle;
6599663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file != NULL,
6609663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
6619663SMark.Logan@Sun.COM 
6629663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult = libntfs_open_attr(libntfs_file)))
6639663SMark.Logan@Sun.COM 		return errvfsresult;
6649663SMark.Logan@Sun.COM 
6659663SMark.Logan@Sun.COM 	switch (whence) {
6669663SMark.Logan@Sun.COM 	case GNOME_VFS_SEEK_START:
6679663SMark.Logan@Sun.COM 		libntfs_file->pos = offset;
6689663SMark.Logan@Sun.COM 		break;
6699663SMark.Logan@Sun.COM 	case GNOME_VFS_SEEK_CURRENT:
6709663SMark.Logan@Sun.COM 		libntfs_file->pos += offset;
6719663SMark.Logan@Sun.COM 		break;
6729663SMark.Logan@Sun.COM 	case GNOME_VFS_SEEK_END:
6739663SMark.Logan@Sun.COM 		/* FIXME: NOT IMPLEMENTED YET */
6749663SMark.Logan@Sun.COM 		g_return_val_if_reached(GNOME_VFS_ERROR_BAD_PARAMETERS);
6759663SMark.Logan@Sun.COM 	default:
6769663SMark.Logan@Sun.COM 		g_assert_not_reached();
6779663SMark.Logan@Sun.COM 	}
6789663SMark.Logan@Sun.COM 
6799663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
6809663SMark.Logan@Sun.COM }
6819663SMark.Logan@Sun.COM 
libntfs_gnomevfs_tell(GnomeVFSMethod * method,GnomeVFSMethodHandle * method_handle,GnomeVFSFileSize * offset_return)6829663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_tell(GnomeVFSMethod *method,
6839663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle *method_handle,
6849663SMark.Logan@Sun.COM 		GnomeVFSFileSize *offset_return)
6859663SMark.Logan@Sun.COM {
6869663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
6879663SMark.Logan@Sun.COM 	struct libntfs_file *libntfs_file;
6889663SMark.Logan@Sun.COM 
6899663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
6909663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
6919663SMark.Logan@Sun.COM 	libntfs_file = (struct libntfs_file *)method_handle;
6929663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file != NULL,
6939663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
6949663SMark.Logan@Sun.COM 	g_return_val_if_fail(offset_return != NULL,
6959663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
6969663SMark.Logan@Sun.COM 
6979663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult = libntfs_open_attr(libntfs_file)))
6989663SMark.Logan@Sun.COM 		return errvfsresult;
6999663SMark.Logan@Sun.COM 
7009663SMark.Logan@Sun.COM 	*offset_return = libntfs_file->pos;
7019663SMark.Logan@Sun.COM 	g_assert((s64)*offset_return == libntfs_file->pos);
7029663SMark.Logan@Sun.COM 
7039663SMark.Logan@Sun.COM 	return errvfsresult;
7049663SMark.Logan@Sun.COM }
7059663SMark.Logan@Sun.COM 
libntfs_gnomevfs_is_local(GnomeVFSMethod * method,const GnomeVFSURI * uri)7069663SMark.Logan@Sun.COM static gboolean libntfs_gnomevfs_is_local(GnomeVFSMethod *method,
7079663SMark.Logan@Sun.COM 		const GnomeVFSURI *uri)
7089663SMark.Logan@Sun.COM {
7099663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
7109663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
7119663SMark.Logan@Sun.COM 	g_return_val_if_fail(uri != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
7129663SMark.Logan@Sun.COM 
7139663SMark.Logan@Sun.COM 	return gnome_vfs_uri_is_local(uri->parent);
7149663SMark.Logan@Sun.COM }
7159663SMark.Logan@Sun.COM 
libntfs_gnomevfs_get_file_info_from_handle(GnomeVFSMethod * method,GnomeVFSMethodHandle * method_handle,GnomeVFSFileInfo * file_info,GnomeVFSFileInfoOptions options,GnomeVFSContext * context)7169663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_get_file_info_from_handle(
7179663SMark.Logan@Sun.COM 		GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle,
7189663SMark.Logan@Sun.COM 		GnomeVFSFileInfo *file_info,
7199663SMark.Logan@Sun.COM 		GnomeVFSFileInfoOptions options __attribute__((unused)),
7209663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
7219663SMark.Logan@Sun.COM {
7229663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
7239663SMark.Logan@Sun.COM 	struct libntfs_file *libntfs_file;
7249663SMark.Logan@Sun.COM 
7259663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
7269663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
7279663SMark.Logan@Sun.COM 	libntfs_file = (struct libntfs_file *)method_handle;
7289663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file != NULL,
7299663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
7309663SMark.Logan@Sun.COM 	g_return_val_if_fail(file_info != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
7319663SMark.Logan@Sun.COM 	/* handle 'options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE'? */
7329663SMark.Logan@Sun.COM 
7339663SMark.Logan@Sun.COM 	file_info->valid_fields = 0;
7349663SMark.Logan@Sun.COM 	/* FIXME: It is complicated to read filename of open 'ntfs_inode'. */
7359663SMark.Logan@Sun.COM 	file_info->name = NULL;
7369663SMark.Logan@Sun.COM 
7379663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult = libntfs_open_attr(libntfs_file))) {
7389663SMark.Logan@Sun.COM 		/* Assume we are directory: */
7399663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_DIRECTORY;
7409663SMark.Logan@Sun.COM 		/*
7419663SMark.Logan@Sun.COM 		 * Do not: file_info->valid_fields |=
7429663SMark.Logan@Sun.COM 		 * GNOME_VFS_FILE_INFO_FIELDS_TYPE;
7439663SMark.Logan@Sun.COM 		 * as gnome-vfs-xfer.c/copy_items() does not check
7449663SMark.Logan@Sun.COM 		 * 'GNOME_VFS_FILE_INFO_FIELDS_TYPE' and we are just bluffing
7459663SMark.Logan@Sun.COM 		 * we know it.
7469663SMark.Logan@Sun.COM 		 */
7479663SMark.Logan@Sun.COM 		return GNOME_VFS_OK;
7489663SMark.Logan@Sun.COM 	}
7499663SMark.Logan@Sun.COM 
7509663SMark.Logan@Sun.COM 	/* FIXME: Is 'data_size' the right field? */
7519663SMark.Logan@Sun.COM 	file_info->size = libntfs_file->attr->data_size;
7529663SMark.Logan@Sun.COM 	file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_SIZE;
7539663SMark.Logan@Sun.COM 
7549663SMark.Logan@Sun.COM 	/*
7559663SMark.Logan@Sun.COM 	 * FIXME: We do not really know the type of 'libntfs_file' but
7569663SMark.Logan@Sun.COM 	 * gnome-vfs-xfer.c/copy_items() requires 'GNOME_VFS_FILE_TYPE_REGULAR'
7579663SMark.Logan@Sun.COM 	 * to copy it.
7589663SMark.Logan@Sun.COM 	 */
7599663SMark.Logan@Sun.COM 	file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
7609663SMark.Logan@Sun.COM 	/*
7619663SMark.Logan@Sun.COM 	 * Do not: file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE;
7629663SMark.Logan@Sun.COM 	 * as gnome-vfs-xfer.c/copy_items() does not check
7639663SMark.Logan@Sun.COM 	 * 'GNOME_VFS_FILE_INFO_FIELDS_TYPE' and we are just bluffing we know
7649663SMark.Logan@Sun.COM 	 * it.
7659663SMark.Logan@Sun.COM 	 */
7669663SMark.Logan@Sun.COM 
7679663SMark.Logan@Sun.COM 	return errvfsresult;
7689663SMark.Logan@Sun.COM }
7699663SMark.Logan@Sun.COM 
libntfs_gnomevfs_get_file_info(GnomeVFSMethod * method,GnomeVFSURI * uri,GnomeVFSFileInfo * file_info,GnomeVFSFileInfoOptions options,GnomeVFSContext * context)7709663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_get_file_info(GnomeVFSMethod *method,
7719663SMark.Logan@Sun.COM 		GnomeVFSURI *uri, GnomeVFSFileInfo *file_info,
7729663SMark.Logan@Sun.COM 		GnomeVFSFileInfoOptions options, GnomeVFSContext *context)
7739663SMark.Logan@Sun.COM {
7749663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
7759663SMark.Logan@Sun.COM 	GnomeVFSMethodHandle *method_handle;
7769663SMark.Logan@Sun.COM 
7779663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
7789663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
7799663SMark.Logan@Sun.COM 	g_return_val_if_fail(file_info != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
7809663SMark.Logan@Sun.COM 	/* handle 'options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE'? */
7819663SMark.Logan@Sun.COM 
7829663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
7839663SMark.Logan@Sun.COM 			libntfs_gnomevfs_open(method, &method_handle, uri,
7849663SMark.Logan@Sun.COM 			GNOME_VFS_OPEN_READ, context)))
7859663SMark.Logan@Sun.COM 		return errvfsresult;
7869663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
7879663SMark.Logan@Sun.COM 			libntfs_gnomevfs_get_file_info_from_handle(method,
7889663SMark.Logan@Sun.COM 			method_handle, file_info, options, context)))
7899663SMark.Logan@Sun.COM 		return errvfsresult;
7909663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
7919663SMark.Logan@Sun.COM 			libntfs_gnomevfs_close(method, method_handle, context)))
7929663SMark.Logan@Sun.COM 		return errvfsresult;
7939663SMark.Logan@Sun.COM 
7949663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
7959663SMark.Logan@Sun.COM }
7969663SMark.Logan@Sun.COM 
libntfs_gnomevfs_check_same_fs(GnomeVFSMethod * method,GnomeVFSURI * a,GnomeVFSURI * b,gboolean * same_fs_return,GnomeVFSContext * context)7979663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_check_same_fs(GnomeVFSMethod *method,
7989663SMark.Logan@Sun.COM 		GnomeVFSURI *a, GnomeVFSURI *b, gboolean *same_fs_return,
7999663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
8009663SMark.Logan@Sun.COM {
8019663SMark.Logan@Sun.COM 	ntfs_volume *volume_a;
8029663SMark.Logan@Sun.COM 	ntfs_volume *volume_b;
8039663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
8049663SMark.Logan@Sun.COM 
8059663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
8069663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
8079663SMark.Logan@Sun.COM 	g_return_val_if_fail(same_fs_return != NULL,
8089663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
8099663SMark.Logan@Sun.COM 
8109663SMark.Logan@Sun.COM 	errvfsresult = libntfs_gnomevfs_uri_parent_init(&volume_a, a);
8119663SMark.Logan@Sun.COM 	g_return_val_if_fail(errvfsresult == GNOME_VFS_OK, errvfsresult);
8129663SMark.Logan@Sun.COM 
8139663SMark.Logan@Sun.COM 	errvfsresult = libntfs_gnomevfs_uri_parent_init(&volume_b, b);
8149663SMark.Logan@Sun.COM 	g_return_val_if_fail(errvfsresult == GNOME_VFS_OK, errvfsresult);
8159663SMark.Logan@Sun.COM 
8169663SMark.Logan@Sun.COM 	*same_fs_return = (volume_a == volume_b);
8179663SMark.Logan@Sun.COM 
8189663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
8199663SMark.Logan@Sun.COM }
8209663SMark.Logan@Sun.COM 
8219663SMark.Logan@Sun.COM /**
8229663SMark.Logan@Sun.COM  * libntfs_gnomevfs_init:
8239663SMark.Logan@Sun.COM  *
8249663SMark.Logan@Sun.COM  * Returns: Initialized structure of #GnomeVFSMethod with static methods of
8259663SMark.Logan@Sun.COM  * libntfs-gnomevfs.
8269663SMark.Logan@Sun.COM  */
libntfs_gnomevfs_method_init(const gchar * method_name,const gchar * args)8279663SMark.Logan@Sun.COM GnomeVFSMethod *libntfs_gnomevfs_method_init(const gchar *method_name,
8289663SMark.Logan@Sun.COM 		const gchar *args)
8299663SMark.Logan@Sun.COM {
8309663SMark.Logan@Sun.COM 	struct method_name_info *method_name_info;
8319663SMark.Logan@Sun.COM 
8329663SMark.Logan@Sun.COM 	g_return_val_if_fail(method_name != NULL, NULL);
8339663SMark.Logan@Sun.COM 	/* 'args' may be NULL if not supplied. */
8349663SMark.Logan@Sun.COM 
8359663SMark.Logan@Sun.COM 	method_name_hash_init();
8369663SMark.Logan@Sun.COM 
8379663SMark.Logan@Sun.COM 	G_LOCK(method_name_hash);
8389663SMark.Logan@Sun.COM 	method_name_info = g_hash_table_lookup(method_name_hash, method_name);
8399663SMark.Logan@Sun.COM 	if (method_name_info && strcmp(method_name_info->args, args))
8409663SMark.Logan@Sun.COM 		method_name_info = NULL;
8419663SMark.Logan@Sun.COM 	G_UNLOCK(method_name_hash);
8429663SMark.Logan@Sun.COM 	if (!method_name_info) {
8439663SMark.Logan@Sun.COM 
8449663SMark.Logan@Sun.COM #ifdef __sun
8459663SMark.Logan@Sun.COM 		method_name_info = g_new(struct method_name_info, 1);
8469663SMark.Logan@Sun.COM #else /* !__sun */
8479663SMark.Logan@Sun.COM 		libntfs_new(method_name_info);
8489663SMark.Logan@Sun.COM #endif /* __sun */
8499663SMark.Logan@Sun.COM 
8509663SMark.Logan@Sun.COM 		method_name_info->args = g_strdup(args);
8519663SMark.Logan@Sun.COM 		G_LOCK(method_name_hash);
8529663SMark.Logan@Sun.COM 		g_hash_table_replace(method_name_hash, g_strdup(method_name),
8539663SMark.Logan@Sun.COM 				method_name_info);
8549663SMark.Logan@Sun.COM 		G_UNLOCK(method_name_hash);
8559663SMark.Logan@Sun.COM 	}
8569663SMark.Logan@Sun.COM 
8579663SMark.Logan@Sun.COM 	G_LOCK(GnomeVFSMethod_static);
8589663SMark.Logan@Sun.COM 	LIBNTFS_MEMZERO(&GnomeVFSMethod_static);
8599663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.method_table_size = sizeof(GnomeVFSMethod_static);
8609663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.open = libntfs_gnomevfs_open;	/* mandatory */
8619663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.create = libntfs_gnomevfs_create;	/* mandatory */
8629663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.close = libntfs_gnomevfs_close;
8639663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.read = libntfs_gnomevfs_read;
8649663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.seek = libntfs_gnomevfs_seek;
8659663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.tell = libntfs_gnomevfs_tell;
8669663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.open_directory = libntfs_gnomevfs_open_directory;
8679663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.close_directory =
8689663SMark.Logan@Sun.COM 			libntfs_gnomevfs_close_directory;
8699663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.read_directory = libntfs_gnomevfs_read_directory;
8709663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.get_file_info =
8719663SMark.Logan@Sun.COM 			libntfs_gnomevfs_get_file_info;	/* mandatory */
8729663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.get_file_info_from_handle =
8739663SMark.Logan@Sun.COM 			libntfs_gnomevfs_get_file_info_from_handle;
8749663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.is_local =
8759663SMark.Logan@Sun.COM 			libntfs_gnomevfs_is_local;	/* mandatory */
8769663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.check_same_fs = libntfs_gnomevfs_check_same_fs;
8779663SMark.Logan@Sun.COM 	/* TODO: GnomeVFSMethodFindDirectoryFunc find_directory; */
8789663SMark.Logan@Sun.COM 	/* TODO: GnomeVFSMethodFileControlFunc file_control; */
8799663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethodCreateSymbolicLinkFunc create_symbolic_link; */
8809663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethodMonitorAddFunc monitor_add; */
8819663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethodMonitorCancelFunc monitor_cancel; */
8829663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.write; */
8839663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.truncate_handle; */
8849663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.make_directory; */
8859663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.remove_directory; */
8869663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.move; */
8879663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.unlink; */
8889663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.set_file_info; */
8899663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.truncate; */
8909663SMark.Logan@Sun.COM 	G_UNLOCK(GnomeVFSMethod_static);
8919663SMark.Logan@Sun.COM 
8929663SMark.Logan@Sun.COM 	return &GnomeVFSMethod_static;
8939663SMark.Logan@Sun.COM }
8949663SMark.Logan@Sun.COM 
8959663SMark.Logan@Sun.COM /**
8969663SMark.Logan@Sun.COM  * libntfs_gnomevfs_method_shutdown:
8979663SMark.Logan@Sun.COM  *
8989663SMark.Logan@Sun.COM  * Shutdowns libntfs-gnomevfs successfuly flushing all caches.
8999663SMark.Logan@Sun.COM  *
9009663SMark.Logan@Sun.COM  * Sad note about gnome-vfs-2.1.5 is that it never calls this function. :-)
9019663SMark.Logan@Sun.COM  */
libntfs_gnomevfs_method_shutdown(void)9029663SMark.Logan@Sun.COM void libntfs_gnomevfs_method_shutdown(void)
9039663SMark.Logan@Sun.COM {
9049663SMark.Logan@Sun.COM 	uri_parent_string_hash_init();
9059663SMark.Logan@Sun.COM 	G_LOCK(uri_parent_string_hash);
9069663SMark.Logan@Sun.COM 	g_hash_table_destroy(uri_parent_string_hash);
9079663SMark.Logan@Sun.COM 	uri_parent_string_hash = NULL;
9089663SMark.Logan@Sun.COM 	G_UNLOCK(uri_parent_string_hash);
9099663SMark.Logan@Sun.COM 
9109663SMark.Logan@Sun.COM 	method_name_hash_init();
9119663SMark.Logan@Sun.COM 	G_LOCK(method_name_hash);
9129663SMark.Logan@Sun.COM 	g_hash_table_destroy(method_name_hash);
9139663SMark.Logan@Sun.COM 	method_name_hash = NULL;
9149663SMark.Logan@Sun.COM 	G_UNLOCK(method_name_hash);
9159663SMark.Logan@Sun.COM }
9169663SMark.Logan@Sun.COM 
917