1*9663SMark.Logan@Sun.COM /*
2*9663SMark.Logan@Sun.COM  * gnome-vfs-method.c - Gnome-VFS init/shutdown implementation of interface to
3*9663SMark.Logan@Sun.COM  *			libntfs. Part of the Linux-NTFS project.
4*9663SMark.Logan@Sun.COM  *
5*9663SMark.Logan@Sun.COM  * Copyright (c) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
6*9663SMark.Logan@Sun.COM  * Copyright (c) 2003-2006 Anton Altaparmakov
7*9663SMark.Logan@Sun.COM  *
8*9663SMark.Logan@Sun.COM  * This program/include file is free software; you can redistribute it and/or
9*9663SMark.Logan@Sun.COM  * modify it under the terms of the GNU General Public License as published
10*9663SMark.Logan@Sun.COM  * by the Free Software Foundation; either version 2 of the License, or
11*9663SMark.Logan@Sun.COM  * (at your option) any later version.
12*9663SMark.Logan@Sun.COM  *
13*9663SMark.Logan@Sun.COM  * This program/include file is distributed in the hope that it will be
14*9663SMark.Logan@Sun.COM  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15*9663SMark.Logan@Sun.COM  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*9663SMark.Logan@Sun.COM  * GNU General Public License for more details.
17*9663SMark.Logan@Sun.COM  *
18*9663SMark.Logan@Sun.COM  * You should have received a copy of the GNU General Public License
19*9663SMark.Logan@Sun.COM  * along with this program (in the main directory of the Linux-NTFS
20*9663SMark.Logan@Sun.COM  * distribution in the file COPYING); if not, write to the Free Software
21*9663SMark.Logan@Sun.COM  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22*9663SMark.Logan@Sun.COM  */
23*9663SMark.Logan@Sun.COM 
24*9663SMark.Logan@Sun.COM #include "config.h"
25*9663SMark.Logan@Sun.COM 
26*9663SMark.Logan@Sun.COM #undef FALSE
27*9663SMark.Logan@Sun.COM #undef TRUE
28*9663SMark.Logan@Sun.COM #include "types.h"		/* for 'FALSE'/'TRUE' libntfs definition */
29*9663SMark.Logan@Sun.COM #define FALSE FALSE
30*9663SMark.Logan@Sun.COM #define TRUE TRUE
31*9663SMark.Logan@Sun.COM 
32*9663SMark.Logan@Sun.COM #include "gnome-vfs-method.h"	/* self */
33*9663SMark.Logan@Sun.COM #include <libgnomevfs/gnome-vfs-method.h>
34*9663SMark.Logan@Sun.COM #include <glib/gmessages.h>
35*9663SMark.Logan@Sun.COM #include "gnome-vfs-module.h"
36*9663SMark.Logan@Sun.COM #include <glib/ghash.h>
37*9663SMark.Logan@Sun.COM #ifdef HAVE_STRING_H
38*9663SMark.Logan@Sun.COM #include <string.h>
39*9663SMark.Logan@Sun.COM #endif
40*9663SMark.Logan@Sun.COM #include <libgnomevfs/gnome-vfs-utils.h>
41*9663SMark.Logan@Sun.COM 
42*9663SMark.Logan@Sun.COM #include "volume.h"
43*9663SMark.Logan@Sun.COM #include "dir.h"
44*9663SMark.Logan@Sun.COM 
45*9663SMark.Logan@Sun.COM static GnomeVFSMethod GnomeVFSMethod_static;
46*9663SMark.Logan@Sun.COM G_LOCK_DEFINE_STATIC(GnomeVFSMethod_static);
47*9663SMark.Logan@Sun.COM 
48*9663SMark.Logan@Sun.COM /* map: (gchar *)method_name -> (struct method_name_info *) */
49*9663SMark.Logan@Sun.COM static GHashTable *method_name_hash;
50*9663SMark.Logan@Sun.COM G_LOCK_DEFINE_STATIC(method_name_hash);
51*9663SMark.Logan@Sun.COM 
52*9663SMark.Logan@Sun.COM #ifdef __sun
53*9663SMark.Logan@Sun.COM G_LOCK_DEFINE(libntfs);
54*9663SMark.Logan@Sun.COM #endif
55*9663SMark.Logan@Sun.COM 
56*9663SMark.Logan@Sun.COM struct method_name_info {
57*9663SMark.Logan@Sun.COM 	gchar *args;
58*9663SMark.Logan@Sun.COM };
59*9663SMark.Logan@Sun.COM 
60*9663SMark.Logan@Sun.COM static void method_name_hash_key_destroy_func(gchar *key)
61*9663SMark.Logan@Sun.COM {
62*9663SMark.Logan@Sun.COM 	g_return_if_fail(key != NULL);
63*9663SMark.Logan@Sun.COM 
64*9663SMark.Logan@Sun.COM 	g_free(key);
65*9663SMark.Logan@Sun.COM }
66*9663SMark.Logan@Sun.COM 
67*9663SMark.Logan@Sun.COM static void method_name_hash_value_destroy_func(struct method_name_info *value)
68*9663SMark.Logan@Sun.COM {
69*9663SMark.Logan@Sun.COM 	g_return_if_fail(value != NULL);
70*9663SMark.Logan@Sun.COM 
71*9663SMark.Logan@Sun.COM 	g_free(value->args);
72*9663SMark.Logan@Sun.COM 	g_free(value);
73*9663SMark.Logan@Sun.COM }
74*9663SMark.Logan@Sun.COM 
75*9663SMark.Logan@Sun.COM static void method_name_hash_init(void)
76*9663SMark.Logan@Sun.COM {
77*9663SMark.Logan@Sun.COM 	G_LOCK(method_name_hash);
78*9663SMark.Logan@Sun.COM 	if (!method_name_hash) {
79*9663SMark.Logan@Sun.COM 		method_name_hash = g_hash_table_new_full(
80*9663SMark.Logan@Sun.COM 				g_str_hash,	/* hash_func */
81*9663SMark.Logan@Sun.COM 				g_str_equal,	/* key_equal_func */
82*9663SMark.Logan@Sun.COM 				(GDestroyNotify) method_name_hash_key_destroy_func,	/* key_destroy_func */
83*9663SMark.Logan@Sun.COM 				(GDestroyNotify) method_name_hash_value_destroy_func);	/* value_destroy_func */
84*9663SMark.Logan@Sun.COM 	}
85*9663SMark.Logan@Sun.COM 	G_UNLOCK(method_name_hash);
86*9663SMark.Logan@Sun.COM }
87*9663SMark.Logan@Sun.COM 
88*9663SMark.Logan@Sun.COM /*
89*9663SMark.Logan@Sun.COM  * map: (gchar *)uri_parent_string "method_name:uri_parent" -> (ntfs_volume *)
90*9663SMark.Logan@Sun.COM  */
91*9663SMark.Logan@Sun.COM static GHashTable *uri_parent_string_hash;
92*9663SMark.Logan@Sun.COM G_LOCK_DEFINE_STATIC(uri_parent_string_hash);
93*9663SMark.Logan@Sun.COM 
94*9663SMark.Logan@Sun.COM static void uri_parent_string_hash_key_destroy_func(gchar *key)
95*9663SMark.Logan@Sun.COM {
96*9663SMark.Logan@Sun.COM 	g_return_if_fail(key != NULL);
97*9663SMark.Logan@Sun.COM 
98*9663SMark.Logan@Sun.COM 	g_free(key);
99*9663SMark.Logan@Sun.COM }
100*9663SMark.Logan@Sun.COM 
101*9663SMark.Logan@Sun.COM static void uri_parent_string_hash_value_destroy_func(ntfs_volume *value)
102*9663SMark.Logan@Sun.COM {
103*9663SMark.Logan@Sun.COM 	g_return_if_fail(value != NULL);
104*9663SMark.Logan@Sun.COM 
105*9663SMark.Logan@Sun.COM 	ntfs_umount(	/* errors ignored */
106*9663SMark.Logan@Sun.COM 			value,	/* vol */
107*9663SMark.Logan@Sun.COM 			TRUE);	/* force; possibly loose modifications */
108*9663SMark.Logan@Sun.COM }
109*9663SMark.Logan@Sun.COM 
110*9663SMark.Logan@Sun.COM static void uri_parent_string_hash_init(void)
111*9663SMark.Logan@Sun.COM {
112*9663SMark.Logan@Sun.COM 	G_LOCK(uri_parent_string_hash);
113*9663SMark.Logan@Sun.COM 	if (!uri_parent_string_hash) {
114*9663SMark.Logan@Sun.COM 		uri_parent_string_hash = g_hash_table_new_full(
115*9663SMark.Logan@Sun.COM 				g_str_hash,	/* hash_func */
116*9663SMark.Logan@Sun.COM 				g_str_equal,	/* key_equal_func */
117*9663SMark.Logan@Sun.COM 				(GDestroyNotify) uri_parent_string_hash_key_destroy_func,	/* key_destroy_func */
118*9663SMark.Logan@Sun.COM 				(GDestroyNotify) uri_parent_string_hash_value_destroy_func);	/* value_destroy_func */
119*9663SMark.Logan@Sun.COM 	}
120*9663SMark.Logan@Sun.COM 	G_UNLOCK(uri_parent_string_hash);
121*9663SMark.Logan@Sun.COM }
122*9663SMark.Logan@Sun.COM 
123*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_uri_parent_init(
124*9663SMark.Logan@Sun.COM 		ntfs_volume **volume_return, GnomeVFSURI *uri)
125*9663SMark.Logan@Sun.COM {
126*9663SMark.Logan@Sun.COM 	gchar *uri_parent_string;
127*9663SMark.Logan@Sun.COM 	gchar *uri_parent_string_parent;
128*9663SMark.Logan@Sun.COM 	ntfs_volume *volume;
129*9663SMark.Logan@Sun.COM 
130*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(uri != NULL, GNOME_VFS_ERROR_INVALID_URI);
131*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(volume_return != NULL,
132*9663SMark.Logan@Sun.COM 			     GNOME_VFS_ERROR_BAD_PARAMETERS);
133*9663SMark.Logan@Sun.COM 
134*9663SMark.Logan@Sun.COM 	uri_parent_string_hash_init();
135*9663SMark.Logan@Sun.COM 
136*9663SMark.Logan@Sun.COM 	if (!uri->parent)
137*9663SMark.Logan@Sun.COM 		return GNOME_VFS_ERROR_INVALID_URI;
138*9663SMark.Logan@Sun.COM 	if (!uri->text)		/* not needed here but we don't permit non-specific fs-image reference */
139*9663SMark.Logan@Sun.COM 		return GNOME_VFS_ERROR_INVALID_URI;
140*9663SMark.Logan@Sun.COM 	uri_parent_string_parent = gnome_vfs_uri_to_string(uri->parent,
141*9663SMark.Logan@Sun.COM 			GNOME_VFS_URI_HIDE_NONE);
142*9663SMark.Logan@Sun.COM 	g_assert(uri_parent_string_parent != NULL);
143*9663SMark.Logan@Sun.COM 
144*9663SMark.Logan@Sun.COM 	uri_parent_string = g_strdup_printf("%s:%s", uri->method_string,
145*9663SMark.Logan@Sun.COM 			uri_parent_string_parent);
146*9663SMark.Logan@Sun.COM 	g_assert(uri_parent_string != NULL);
147*9663SMark.Logan@Sun.COM 
148*9663SMark.Logan@Sun.COM 	G_LOCK(uri_parent_string_hash);
149*9663SMark.Logan@Sun.COM 	volume = g_hash_table_lookup(uri_parent_string_hash, uri_parent_string);
150*9663SMark.Logan@Sun.COM 	G_UNLOCK(uri_parent_string_hash);
151*9663SMark.Logan@Sun.COM 	if (!volume) {
152*9663SMark.Logan@Sun.COM 		struct method_name_info *method_name_info;
153*9663SMark.Logan@Sun.COM 
154*9663SMark.Logan@Sun.COM 		G_LOCK(method_name_hash);
155*9663SMark.Logan@Sun.COM 		method_name_info = g_hash_table_lookup(method_name_hash,
156*9663SMark.Logan@Sun.COM 				uri->method_string);
157*9663SMark.Logan@Sun.COM 		G_UNLOCK(method_name_hash);
158*9663SMark.Logan@Sun.COM 		if (!method_name_info) {
159*9663SMark.Logan@Sun.COM 			/* should not happend */
160*9663SMark.Logan@Sun.COM 			g_return_val_if_reached(GNOME_VFS_ERROR_INVALID_URI);
161*9663SMark.Logan@Sun.COM 		}
162*9663SMark.Logan@Sun.COM 
163*9663SMark.Logan@Sun.COM 		/* TODO: Generic GnomeVFS filter. */
164*9663SMark.Logan@Sun.COM 		if (strcmp(uri->parent->method_string, "file")) {
165*9663SMark.Logan@Sun.COM 			g_free(uri_parent_string);
166*9663SMark.Logan@Sun.COM 			return GNOME_VFS_ERROR_INVALID_URI;
167*9663SMark.Logan@Sun.COM 		}
168*9663SMark.Logan@Sun.COM 
169*9663SMark.Logan@Sun.COM 		if (!(volume = ntfs_mount(uri->parent->text,
170*9663SMark.Logan@Sun.COM 				NTFS_MNT_RDONLY))) {
171*9663SMark.Logan@Sun.COM 			g_free(uri_parent_string);
172*9663SMark.Logan@Sun.COM 			return GNOME_VFS_ERROR_WRONG_FORMAT;
173*9663SMark.Logan@Sun.COM 		}
174*9663SMark.Logan@Sun.COM 
175*9663SMark.Logan@Sun.COM 		G_LOCK(uri_parent_string_hash);
176*9663SMark.Logan@Sun.COM 		g_hash_table_insert(uri_parent_string_hash,
177*9663SMark.Logan@Sun.COM 				g_strdup(uri_parent_string), volume);
178*9663SMark.Logan@Sun.COM 		G_UNLOCK(uri_parent_string_hash);
179*9663SMark.Logan@Sun.COM 	}
180*9663SMark.Logan@Sun.COM 	g_free(uri_parent_string);
181*9663SMark.Logan@Sun.COM 
182*9663SMark.Logan@Sun.COM 	*volume_return = volume;
183*9663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
184*9663SMark.Logan@Sun.COM }
185*9663SMark.Logan@Sun.COM 
186*9663SMark.Logan@Sun.COM static GnomeVFSResult inode_open_by_pathname(ntfs_inode **inode_return,
187*9663SMark.Logan@Sun.COM 		ntfs_volume *volume, const gchar *pathname)
188*9663SMark.Logan@Sun.COM {
189*9663SMark.Logan@Sun.COM 	MFT_REF mref;
190*9663SMark.Logan@Sun.COM 	ntfs_inode *inode;
191*9663SMark.Logan@Sun.COM 	gchar *pathname_parse, *pathname_next;
192*9663SMark.Logan@Sun.COM 	int errint;
193*9663SMark.Logan@Sun.COM 
194*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(inode_return != NULL,
195*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
196*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(volume != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
197*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(pathname != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
198*9663SMark.Logan@Sun.COM 
199*9663SMark.Logan@Sun.COM 	pathname = g_path_skip_root(pathname);
200*9663SMark.Logan@Sun.COM 	pathname_parse = g_alloca(strlen(pathname) + 1);
201*9663SMark.Logan@Sun.COM 	strcpy(pathname_parse, pathname);
202*9663SMark.Logan@Sun.COM 	mref = FILE_root;
203*9663SMark.Logan@Sun.COM 	for (;;) {
204*9663SMark.Logan@Sun.COM 		ntfschar *pathname_parse_ucs2;
205*9663SMark.Logan@Sun.COM 		gchar *pathname_parse_unescaped;
206*9663SMark.Logan@Sun.COM 		int i;
207*9663SMark.Logan@Sun.COM 
208*9663SMark.Logan@Sun.COM 		G_LOCK(libntfs);
209*9663SMark.Logan@Sun.COM 		inode = ntfs_inode_open(volume, mref);
210*9663SMark.Logan@Sun.COM 		G_UNLOCK(libntfs);
211*9663SMark.Logan@Sun.COM 		if (!inode)
212*9663SMark.Logan@Sun.COM 			return GNOME_VFS_ERROR_NOT_FOUND;
213*9663SMark.Logan@Sun.COM 		if (!*pathname_parse) {
214*9663SMark.Logan@Sun.COM 			*inode_return = inode;
215*9663SMark.Logan@Sun.COM 			return GNOME_VFS_OK;
216*9663SMark.Logan@Sun.COM 		}
217*9663SMark.Logan@Sun.COM 		for (pathname_next = pathname_parse; *pathname_next &&
218*9663SMark.Logan@Sun.COM 		     *pathname_next != G_DIR_SEPARATOR; pathname_next++) ;
219*9663SMark.Logan@Sun.COM 		if (*pathname_next) {
220*9663SMark.Logan@Sun.COM 			/* terminate current path element */
221*9663SMark.Logan@Sun.COM 			*pathname_next++ = 0;
222*9663SMark.Logan@Sun.COM 		}
223*9663SMark.Logan@Sun.COM 		while (*pathname_next == G_DIR_SEPARATOR)
224*9663SMark.Logan@Sun.COM 			pathname_next++;
225*9663SMark.Logan@Sun.COM 		/* FIXME: Is 'pathname' utf8? */
226*9663SMark.Logan@Sun.COM 		pathname_parse_unescaped = gnome_vfs_unescape_string(
227*9663SMark.Logan@Sun.COM 				pathname_parse, NULL);	/* illegal_characters */
228*9663SMark.Logan@Sun.COM #ifdef __sun
229*9663SMark.Logan@Sun.COM 		pathname_parse_ucs2 = g_malloc(strlen(pathname_parse_unescaped) + 1);
230*9663SMark.Logan@Sun.COM #else /* !__sun */
231*9663SMark.Logan@Sun.COM 		libntfs_newn(pathname_parse_ucs2,
232*9663SMark.Logan@Sun.COM 				strlen(pathname_parse_unescaped) + 1);
233*9663SMark.Logan@Sun.COM #endif /* __sun */
234*9663SMark.Logan@Sun.COM 		for (i = 0; pathname_parse_unescaped[i]; i++)
235*9663SMark.Logan@Sun.COM 			pathname_parse_ucs2[i] = cpu_to_le16(
236*9663SMark.Logan@Sun.COM 					pathname_parse_unescaped[i]);
237*9663SMark.Logan@Sun.COM 		pathname_parse_ucs2[i] = 0;
238*9663SMark.Logan@Sun.COM 		g_free(pathname_parse_unescaped);
239*9663SMark.Logan@Sun.COM 		G_LOCK(libntfs);
240*9663SMark.Logan@Sun.COM 		mref = ntfs_inode_lookup_by_name(inode, pathname_parse_ucs2, i);
241*9663SMark.Logan@Sun.COM 		G_UNLOCK(libntfs);
242*9663SMark.Logan@Sun.COM 		g_free(pathname_parse_ucs2);
243*9663SMark.Logan@Sun.COM 		if ((MFT_REF)-1 == mref)
244*9663SMark.Logan@Sun.COM 			return GNOME_VFS_ERROR_NOT_FOUND;
245*9663SMark.Logan@Sun.COM 		G_LOCK(libntfs);
246*9663SMark.Logan@Sun.COM 		errint = ntfs_inode_close(inode);
247*9663SMark.Logan@Sun.COM 		G_UNLOCK(libntfs);
248*9663SMark.Logan@Sun.COM 		if (errint)
249*9663SMark.Logan@Sun.COM 			g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
250*9663SMark.Logan@Sun.COM 		pathname_parse = pathname_next;
251*9663SMark.Logan@Sun.COM 	}
252*9663SMark.Logan@Sun.COM 	/* NOTREACHED */
253*9663SMark.Logan@Sun.COM }
254*9663SMark.Logan@Sun.COM 
255*9663SMark.Logan@Sun.COM struct libntfs_directory {
256*9663SMark.Logan@Sun.COM 	ntfs_inode *inode;
257*9663SMark.Logan@Sun.COM 	GList *file_info_list;	/* of (GnomeVFSFileInfo *); last item has ->data == NULL */
258*9663SMark.Logan@Sun.COM };
259*9663SMark.Logan@Sun.COM 
260*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_open_directory(GnomeVFSMethod *method,
261*9663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle **method_handle, GnomeVFSURI *uri,
262*9663SMark.Logan@Sun.COM 		GnomeVFSFileInfoOptions options __attribute__((unused)),
263*9663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
264*9663SMark.Logan@Sun.COM {
265*9663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
266*9663SMark.Logan@Sun.COM 	ntfs_volume *volume;
267*9663SMark.Logan@Sun.COM 	ntfs_inode *inode;
268*9663SMark.Logan@Sun.COM 	struct libntfs_directory *libntfs_directory;
269*9663SMark.Logan@Sun.COM 
270*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
271*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
272*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method_handle != NULL,
273*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
274*9663SMark.Logan@Sun.COM 
275*9663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
276*9663SMark.Logan@Sun.COM 			libntfs_gnomevfs_uri_parent_init(&volume, uri)))
277*9663SMark.Logan@Sun.COM 		return errvfsresult;
278*9663SMark.Logan@Sun.COM 
279*9663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult = inode_open_by_pathname(&inode,
280*9663SMark.Logan@Sun.COM 			volume, uri->text)))
281*9663SMark.Logan@Sun.COM 		return errvfsresult;
282*9663SMark.Logan@Sun.COM 
283*9663SMark.Logan@Sun.COM #ifdef __sun
284*9663SMark.Logan@Sun.COM 	libntfs_directory = g_new(struct libntfs_directory, 1);
285*9663SMark.Logan@Sun.COM #else /* !__sun */
286*9663SMark.Logan@Sun.COM 	libntfs_new(libntfs_directory);
287*9663SMark.Logan@Sun.COM #endif /* __sun */
288*9663SMark.Logan@Sun.COM 
289*9663SMark.Logan@Sun.COM 	libntfs_directory->inode = inode;
290*9663SMark.Logan@Sun.COM 	libntfs_directory->file_info_list = NULL;
291*9663SMark.Logan@Sun.COM 
292*9663SMark.Logan@Sun.COM 	*method_handle = (GnomeVFSMethodHandle *)libntfs_directory;
293*9663SMark.Logan@Sun.COM 	return errvfsresult;
294*9663SMark.Logan@Sun.COM }
295*9663SMark.Logan@Sun.COM 
296*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_close_directory(GnomeVFSMethod *method,
297*9663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle *method_handle,
298*9663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
299*9663SMark.Logan@Sun.COM {
300*9663SMark.Logan@Sun.COM 	struct libntfs_directory *libntfs_directory;
301*9663SMark.Logan@Sun.COM 	int errint;
302*9663SMark.Logan@Sun.COM 
303*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
304*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
305*9663SMark.Logan@Sun.COM 	libntfs_directory = (struct libntfs_directory *)method_handle;
306*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_directory != NULL,
307*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
308*9663SMark.Logan@Sun.COM 
309*9663SMark.Logan@Sun.COM 	G_LOCK(libntfs);
310*9663SMark.Logan@Sun.COM 	errint = ntfs_inode_close(libntfs_directory->inode);
311*9663SMark.Logan@Sun.COM 	G_UNLOCK(libntfs);
312*9663SMark.Logan@Sun.COM 	if (errint)
313*9663SMark.Logan@Sun.COM 		g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
314*9663SMark.Logan@Sun.COM 
315*9663SMark.Logan@Sun.COM 	if (libntfs_directory->file_info_list) {
316*9663SMark.Logan@Sun.COM 		GList *last_l;
317*9663SMark.Logan@Sun.COM 
318*9663SMark.Logan@Sun.COM 		/*
319*9663SMark.Logan@Sun.COM 		 * Prevent gnome_vfs_file_info_list_free() and its
320*9663SMark.Logan@Sun.COM 		 * gnome_vfs_file_info_unref() on the last 'file_info_list'
321*9663SMark.Logan@Sun.COM 		 * items as it is EOF with NULL '->data'.
322*9663SMark.Logan@Sun.COM 		 */
323*9663SMark.Logan@Sun.COM 		last_l = g_list_last(libntfs_directory->file_info_list);
324*9663SMark.Logan@Sun.COM 		g_assert(last_l->data == NULL);
325*9663SMark.Logan@Sun.COM 		libntfs_directory->file_info_list = g_list_delete_link(
326*9663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list, last_l);
327*9663SMark.Logan@Sun.COM 		gnome_vfs_file_info_list_free(
328*9663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list);
329*9663SMark.Logan@Sun.COM 	}
330*9663SMark.Logan@Sun.COM 
331*9663SMark.Logan@Sun.COM 	g_free(libntfs_directory);
332*9663SMark.Logan@Sun.COM 
333*9663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
334*9663SMark.Logan@Sun.COM }
335*9663SMark.Logan@Sun.COM 
336*9663SMark.Logan@Sun.COM static gchar *libntfs_ntfscharo_utf8(const ntfschar *name, const int name_len)
337*9663SMark.Logan@Sun.COM {
338*9663SMark.Logan@Sun.COM 	GString *gstring;
339*9663SMark.Logan@Sun.COM 	int i;
340*9663SMark.Logan@Sun.COM 
341*9663SMark.Logan@Sun.COM 	gstring = g_string_sized_new(name_len);
342*9663SMark.Logan@Sun.COM 	for (i = 0; i < name_len; i++)
343*9663SMark.Logan@Sun.COM 		gstring = g_string_append_unichar(gstring,
344*9663SMark.Logan@Sun.COM 				le16_to_cpu(name[i]));
345*9663SMark.Logan@Sun.COM 	return g_string_free(gstring,	/* returns utf8-formatted string */
346*9663SMark.Logan@Sun.COM 			FALSE);	/* free_segment */
347*9663SMark.Logan@Sun.COM }
348*9663SMark.Logan@Sun.COM 
349*9663SMark.Logan@Sun.COM /*
350*9663SMark.Logan@Sun.COM  * Do not lock 'libntfs' here as we are already locked inside ntfs_readdir().
351*9663SMark.Logan@Sun.COM  */
352*9663SMark.Logan@Sun.COM static int libntfs_gnomevfs_read_directory_filldir(
353*9663SMark.Logan@Sun.COM 		struct libntfs_directory *libntfs_directory /* dirent */,
354*9663SMark.Logan@Sun.COM 		const ntfschar *name, const int name_len,
355*9663SMark.Logan@Sun.COM 		const int name_type __attribute__((unused)),
356*9663SMark.Logan@Sun.COM 		const s64 pos, const MFT_REF mref, const unsigned dt_type)
357*9663SMark.Logan@Sun.COM {
358*9663SMark.Logan@Sun.COM 	GnomeVFSFileInfo *file_info;
359*9663SMark.Logan@Sun.COM 
360*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_directory != NULL, -1);
361*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(name != NULL, -1);
362*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(name_len >= 0, -1);
363*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(pos >= 0, -1);
364*9663SMark.Logan@Sun.COM 
365*9663SMark.Logan@Sun.COM 	/* system directory */
366*9663SMark.Logan@Sun.COM 	if (MREF(mref) != FILE_root && MREF(mref) < FILE_first_user)
367*9663SMark.Logan@Sun.COM 		return 0;	/* continue traversal */
368*9663SMark.Logan@Sun.COM 
369*9663SMark.Logan@Sun.COM 	file_info = gnome_vfs_file_info_new();
370*9663SMark.Logan@Sun.COM 	file_info->name = libntfs_ntfscharo_utf8(name, name_len);
371*9663SMark.Logan@Sun.COM 	file_info->valid_fields = 0;
372*9663SMark.Logan@Sun.COM 
373*9663SMark.Logan@Sun.COM 	switch (dt_type) {
374*9663SMark.Logan@Sun.COM 	case NTFS_DT_FIFO:
375*9663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_FIFO;
376*9663SMark.Logan@Sun.COM 		break;
377*9663SMark.Logan@Sun.COM 	case NTFS_DT_CHR:
378*9663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE;
379*9663SMark.Logan@Sun.COM 		break;
380*9663SMark.Logan@Sun.COM 	case NTFS_DT_DIR:
381*9663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_DIRECTORY;
382*9663SMark.Logan@Sun.COM 		break;
383*9663SMark.Logan@Sun.COM 	case NTFS_DT_BLK:
384*9663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_BLOCK_DEVICE;
385*9663SMark.Logan@Sun.COM 		break;
386*9663SMark.Logan@Sun.COM 	case NTFS_DT_REG:
387*9663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
388*9663SMark.Logan@Sun.COM 		break;
389*9663SMark.Logan@Sun.COM 	case NTFS_DT_LNK:
390*9663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK;
391*9663SMark.Logan@Sun.COM 		break;
392*9663SMark.Logan@Sun.COM 	case NTFS_DT_SOCK:
393*9663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
394*9663SMark.Logan@Sun.COM 		break;
395*9663SMark.Logan@Sun.COM 		/* FIXME: What is 'NTFS_DT_WHT'? */
396*9663SMark.Logan@Sun.COM 	default:
397*9663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_UNKNOWN;
398*9663SMark.Logan@Sun.COM 	}
399*9663SMark.Logan@Sun.COM 	if (file_info->type != GNOME_VFS_FILE_TYPE_UNKNOWN)
400*9663SMark.Logan@Sun.COM 		file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_TYPE;
401*9663SMark.Logan@Sun.COM 
402*9663SMark.Logan@Sun.COM 	/* Detect 'file_info->size': */
403*9663SMark.Logan@Sun.COM 	if (file_info->type == GNOME_VFS_FILE_TYPE_REGULAR) {
404*9663SMark.Logan@Sun.COM 		ntfs_inode *inode;
405*9663SMark.Logan@Sun.COM 
406*9663SMark.Logan@Sun.COM 		inode = ntfs_inode_open(libntfs_directory->inode->vol, mref);
407*9663SMark.Logan@Sun.COM 		/* FIXME: Check failed 'inode' open. */
408*9663SMark.Logan@Sun.COM 		if (inode) {
409*9663SMark.Logan@Sun.COM 			ntfs_attr *attr;
410*9663SMark.Logan@Sun.COM 			int errint;
411*9663SMark.Logan@Sun.COM 
412*9663SMark.Logan@Sun.COM 			attr = ntfs_attr_open(inode,	/* ni */
413*9663SMark.Logan@Sun.COM 					AT_DATA,	/* type */
414*9663SMark.Logan@Sun.COM 					AT_UNNAMED,	/* name */
415*9663SMark.Logan@Sun.COM 					0);		/* name_len */
416*9663SMark.Logan@Sun.COM 			/* FIXME: Check failed 'attr' open. */
417*9663SMark.Logan@Sun.COM 			if (attr) {
418*9663SMark.Logan@Sun.COM 				/* FIXME: Is 'data_size' the right field? */
419*9663SMark.Logan@Sun.COM 				file_info->size = attr->data_size;
420*9663SMark.Logan@Sun.COM 				file_info->valid_fields |=
421*9663SMark.Logan@Sun.COM 						GNOME_VFS_FILE_INFO_FIELDS_SIZE;
422*9663SMark.Logan@Sun.COM 				ntfs_attr_close(attr);
423*9663SMark.Logan@Sun.COM 			}
424*9663SMark.Logan@Sun.COM 			errint = ntfs_inode_close(inode);
425*9663SMark.Logan@Sun.COM 			/* FIXME: Check 'errint'. */
426*9663SMark.Logan@Sun.COM 		}
427*9663SMark.Logan@Sun.COM 	}
428*9663SMark.Logan@Sun.COM 
429*9663SMark.Logan@Sun.COM 	libntfs_directory->file_info_list = g_list_prepend(
430*9663SMark.Logan@Sun.COM 			libntfs_directory->file_info_list, file_info);
431*9663SMark.Logan@Sun.COM 
432*9663SMark.Logan@Sun.COM 	return 0;	/* continue traversal */
433*9663SMark.Logan@Sun.COM }
434*9663SMark.Logan@Sun.COM 
435*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_read_directory(GnomeVFSMethod *method,
436*9663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle *method_handle,
437*9663SMark.Logan@Sun.COM 		GnomeVFSFileInfo *file_info,
438*9663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
439*9663SMark.Logan@Sun.COM {
440*9663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
441*9663SMark.Logan@Sun.COM 	struct libntfs_directory *libntfs_directory;
442*9663SMark.Logan@Sun.COM 
443*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
444*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
445*9663SMark.Logan@Sun.COM 	libntfs_directory = (struct libntfs_directory *)method_handle;
446*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_directory != NULL,
447*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
448*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(file_info != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
449*9663SMark.Logan@Sun.COM 
450*9663SMark.Logan@Sun.COM 	if (!libntfs_directory->file_info_list) {
451*9663SMark.Logan@Sun.COM 		int errint;
452*9663SMark.Logan@Sun.COM 		s64 pos;
453*9663SMark.Logan@Sun.COM 
454*9663SMark.Logan@Sun.COM 		pos = 0; /* read from the start; incl. "." and ".." entries */
455*9663SMark.Logan@Sun.COM 		G_LOCK(libntfs);
456*9663SMark.Logan@Sun.COM 		errint = ntfs_readdir(libntfs_directory->inode,	/* dir_ni */
457*9663SMark.Logan@Sun.COM 				&pos,	/* pos */
458*9663SMark.Logan@Sun.COM 				libntfs_directory,	/* dirent */
459*9663SMark.Logan@Sun.COM 				(ntfs_filldir_t)libntfs_gnomevfs_read_directory_filldir);	/* filldir */
460*9663SMark.Logan@Sun.COM 		G_UNLOCK(libntfs);
461*9663SMark.Logan@Sun.COM 		if (errint)
462*9663SMark.Logan@Sun.COM 			return GNOME_VFS_ERROR_INTERNAL;
463*9663SMark.Logan@Sun.COM 
464*9663SMark.Logan@Sun.COM 		libntfs_directory->file_info_list = g_list_prepend(
465*9663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list, NULL); /* EOF */
466*9663SMark.Logan@Sun.COM 		libntfs_directory->file_info_list = g_list_reverse(
467*9663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list);
468*9663SMark.Logan@Sun.COM 	}
469*9663SMark.Logan@Sun.COM 
470*9663SMark.Logan@Sun.COM 	if (!libntfs_directory->file_info_list->data) {
471*9663SMark.Logan@Sun.COM 		g_assert(libntfs_directory->file_info_list->next == NULL);
472*9663SMark.Logan@Sun.COM 		/*
473*9663SMark.Logan@Sun.COM 		 * Do not clear the list to leave us stuck at EOF - GnomeVFS
474*9663SMark.Logan@Sun.COM 		 * behaves that way.
475*9663SMark.Logan@Sun.COM 		 */
476*9663SMark.Logan@Sun.COM 		errvfsresult = GNOME_VFS_ERROR_EOF;
477*9663SMark.Logan@Sun.COM 	} else {
478*9663SMark.Logan@Sun.COM 		/* Cut first list item. */
479*9663SMark.Logan@Sun.COM 		gnome_vfs_file_info_copy(file_info, /* dest */
480*9663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list->data); /* src */
481*9663SMark.Logan@Sun.COM 		gnome_vfs_file_info_unref(
482*9663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list->data);
483*9663SMark.Logan@Sun.COM 		libntfs_directory->file_info_list = g_list_delete_link(
484*9663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list,
485*9663SMark.Logan@Sun.COM 				libntfs_directory->file_info_list);
486*9663SMark.Logan@Sun.COM 		errvfsresult = GNOME_VFS_OK;
487*9663SMark.Logan@Sun.COM 	}
488*9663SMark.Logan@Sun.COM 	return errvfsresult;
489*9663SMark.Logan@Sun.COM }
490*9663SMark.Logan@Sun.COM 
491*9663SMark.Logan@Sun.COM struct libntfs_file {
492*9663SMark.Logan@Sun.COM 	ntfs_inode *inode;
493*9663SMark.Logan@Sun.COM 	ntfs_attr *attr;
494*9663SMark.Logan@Sun.COM 	s64 pos;
495*9663SMark.Logan@Sun.COM };
496*9663SMark.Logan@Sun.COM 
497*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_open_attr(struct libntfs_file *libntfs_file)
498*9663SMark.Logan@Sun.COM {
499*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file != NULL,
500*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
501*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file->inode != NULL,
502*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
503*9663SMark.Logan@Sun.COM 
504*9663SMark.Logan@Sun.COM 	if (!libntfs_file->attr) {
505*9663SMark.Logan@Sun.COM 		G_LOCK(libntfs);
506*9663SMark.Logan@Sun.COM 		libntfs_file->attr = ntfs_attr_open(
507*9663SMark.Logan@Sun.COM 				libntfs_file->inode,	/* ni */
508*9663SMark.Logan@Sun.COM 				AT_DATA,	/* type */
509*9663SMark.Logan@Sun.COM 				AT_UNNAMED,	/* name */
510*9663SMark.Logan@Sun.COM 				0);	/* name_len */
511*9663SMark.Logan@Sun.COM 		G_UNLOCK(libntfs);
512*9663SMark.Logan@Sun.COM 		if (!libntfs_file->attr)
513*9663SMark.Logan@Sun.COM 			return GNOME_VFS_ERROR_BAD_FILE;
514*9663SMark.Logan@Sun.COM 		libntfs_file->pos = 0;
515*9663SMark.Logan@Sun.COM 	}
516*9663SMark.Logan@Sun.COM 
517*9663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
518*9663SMark.Logan@Sun.COM }
519*9663SMark.Logan@Sun.COM 
520*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_open(GnomeVFSMethod *method,
521*9663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle **method_handle_return, GnomeVFSURI *uri,
522*9663SMark.Logan@Sun.COM 		GnomeVFSOpenMode mode,
523*9663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
524*9663SMark.Logan@Sun.COM {
525*9663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
526*9663SMark.Logan@Sun.COM 	ntfs_volume *volume;
527*9663SMark.Logan@Sun.COM 	ntfs_inode *inode;
528*9663SMark.Logan@Sun.COM 	struct libntfs_file *libntfs_file;
529*9663SMark.Logan@Sun.COM 
530*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
531*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
532*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method_handle_return != NULL,
533*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
534*9663SMark.Logan@Sun.COM 
535*9663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
536*9663SMark.Logan@Sun.COM 			libntfs_gnomevfs_uri_parent_init(&volume, uri)))
537*9663SMark.Logan@Sun.COM 		return errvfsresult;
538*9663SMark.Logan@Sun.COM 
539*9663SMark.Logan@Sun.COM 	if (mode & GNOME_VFS_OPEN_WRITE)
540*9663SMark.Logan@Sun.COM 		return GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM;
541*9663SMark.Logan@Sun.COM 
542*9663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
543*9663SMark.Logan@Sun.COM 			inode_open_by_pathname(&inode, volume, uri->text)))
544*9663SMark.Logan@Sun.COM 		return errvfsresult;
545*9663SMark.Logan@Sun.COM 
546*9663SMark.Logan@Sun.COM #ifdef __sun
547*9663SMark.Logan@Sun.COM 	libntfs_file = g_new(struct libntfs_file, 1);
548*9663SMark.Logan@Sun.COM #else /* !__sun */
549*9663SMark.Logan@Sun.COM 	libntfs_new(libntfs_file);
550*9663SMark.Logan@Sun.COM #endif /* __sun */
551*9663SMark.Logan@Sun.COM 
552*9663SMark.Logan@Sun.COM 	libntfs_file->inode = inode;
553*9663SMark.Logan@Sun.COM 	libntfs_file->attr = NULL;
554*9663SMark.Logan@Sun.COM 
555*9663SMark.Logan@Sun.COM 	*method_handle_return = (GnomeVFSMethodHandle *)libntfs_file;
556*9663SMark.Logan@Sun.COM 	return errvfsresult;
557*9663SMark.Logan@Sun.COM }
558*9663SMark.Logan@Sun.COM 
559*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_create(GnomeVFSMethod *method,
560*9663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle **method_handle_return, GnomeVFSURI *uri,
561*9663SMark.Logan@Sun.COM 		GnomeVFSOpenMode mode __attribute__((unused)),
562*9663SMark.Logan@Sun.COM 		gboolean exclusive __attribute__((unused)),
563*9663SMark.Logan@Sun.COM 		guint perm __attribute__((unused)),
564*9663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
565*9663SMark.Logan@Sun.COM {
566*9663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
567*9663SMark.Logan@Sun.COM 	ntfs_volume *volume;
568*9663SMark.Logan@Sun.COM 
569*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
570*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
571*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method_handle_return != NULL,
572*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
573*9663SMark.Logan@Sun.COM 
574*9663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
575*9663SMark.Logan@Sun.COM 			libntfs_gnomevfs_uri_parent_init(&volume, uri)))
576*9663SMark.Logan@Sun.COM 		return errvfsresult;
577*9663SMark.Logan@Sun.COM 
578*9663SMark.Logan@Sun.COM 	return GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM;
579*9663SMark.Logan@Sun.COM }
580*9663SMark.Logan@Sun.COM 
581*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_close(GnomeVFSMethod *method,
582*9663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle *method_handle,
583*9663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
584*9663SMark.Logan@Sun.COM {
585*9663SMark.Logan@Sun.COM 	struct libntfs_file *libntfs_file;
586*9663SMark.Logan@Sun.COM 	int errint;
587*9663SMark.Logan@Sun.COM 
588*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
589*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
590*9663SMark.Logan@Sun.COM 	libntfs_file = (struct libntfs_file *) method_handle;
591*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file != NULL,
592*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
593*9663SMark.Logan@Sun.COM 
594*9663SMark.Logan@Sun.COM 	if (libntfs_file->attr) {
595*9663SMark.Logan@Sun.COM 		G_LOCK(libntfs);
596*9663SMark.Logan@Sun.COM 		ntfs_attr_close(libntfs_file->attr);
597*9663SMark.Logan@Sun.COM 		G_UNLOCK(libntfs);
598*9663SMark.Logan@Sun.COM 	}
599*9663SMark.Logan@Sun.COM 	G_LOCK(libntfs);
600*9663SMark.Logan@Sun.COM 	errint = ntfs_inode_close(libntfs_file->inode);
601*9663SMark.Logan@Sun.COM 	G_UNLOCK(libntfs);
602*9663SMark.Logan@Sun.COM 	if (errint)
603*9663SMark.Logan@Sun.COM 		g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
604*9663SMark.Logan@Sun.COM 
605*9663SMark.Logan@Sun.COM 	g_free(libntfs_file);
606*9663SMark.Logan@Sun.COM 
607*9663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
608*9663SMark.Logan@Sun.COM }
609*9663SMark.Logan@Sun.COM 
610*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_read(GnomeVFSMethod *method,
611*9663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle *method_handle, gpointer buffer,
612*9663SMark.Logan@Sun.COM 		GnomeVFSFileSize num_bytes, GnomeVFSFileSize *bytes_read_return,
613*9663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
614*9663SMark.Logan@Sun.COM {
615*9663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
616*9663SMark.Logan@Sun.COM 	struct libntfs_file *libntfs_file;
617*9663SMark.Logan@Sun.COM 	s64 count_s64, got;
618*9663SMark.Logan@Sun.COM 
619*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
620*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
621*9663SMark.Logan@Sun.COM 	libntfs_file = (struct libntfs_file *)method_handle;
622*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file != NULL,
623*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
624*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(buffer != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
625*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(bytes_read_return != NULL,
626*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
627*9663SMark.Logan@Sun.COM 
628*9663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult = libntfs_open_attr(libntfs_file)))
629*9663SMark.Logan@Sun.COM 		return errvfsresult;
630*9663SMark.Logan@Sun.COM 
631*9663SMark.Logan@Sun.COM 	count_s64 = num_bytes;
632*9663SMark.Logan@Sun.COM 	g_assert((GnomeVFSFileSize)count_s64 == num_bytes);
633*9663SMark.Logan@Sun.COM 	G_LOCK(libntfs);
634*9663SMark.Logan@Sun.COM 	got = ntfs_attr_pread(libntfs_file->attr, libntfs_file->pos, count_s64,
635*9663SMark.Logan@Sun.COM 			buffer);
636*9663SMark.Logan@Sun.COM 	G_UNLOCK(libntfs);
637*9663SMark.Logan@Sun.COM 	if (got == -1)
638*9663SMark.Logan@Sun.COM 		return GNOME_VFS_ERROR_IO;
639*9663SMark.Logan@Sun.COM 
640*9663SMark.Logan@Sun.COM 	libntfs_file->pos += got;
641*9663SMark.Logan@Sun.COM 	*bytes_read_return = got;
642*9663SMark.Logan@Sun.COM 	g_assert((s64)*bytes_read_return == got);
643*9663SMark.Logan@Sun.COM 
644*9663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
645*9663SMark.Logan@Sun.COM }
646*9663SMark.Logan@Sun.COM 
647*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_seek(GnomeVFSMethod *method,
648*9663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle *method_handle,
649*9663SMark.Logan@Sun.COM 		GnomeVFSSeekPosition whence, GnomeVFSFileOffset offset,
650*9663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
651*9663SMark.Logan@Sun.COM {
652*9663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
653*9663SMark.Logan@Sun.COM 	struct libntfs_file *libntfs_file;
654*9663SMark.Logan@Sun.COM 
655*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
656*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
657*9663SMark.Logan@Sun.COM 	libntfs_file = (struct libntfs_file *)method_handle;
658*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file != NULL,
659*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
660*9663SMark.Logan@Sun.COM 
661*9663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult = libntfs_open_attr(libntfs_file)))
662*9663SMark.Logan@Sun.COM 		return errvfsresult;
663*9663SMark.Logan@Sun.COM 
664*9663SMark.Logan@Sun.COM 	switch (whence) {
665*9663SMark.Logan@Sun.COM 	case GNOME_VFS_SEEK_START:
666*9663SMark.Logan@Sun.COM 		libntfs_file->pos = offset;
667*9663SMark.Logan@Sun.COM 		break;
668*9663SMark.Logan@Sun.COM 	case GNOME_VFS_SEEK_CURRENT:
669*9663SMark.Logan@Sun.COM 		libntfs_file->pos += offset;
670*9663SMark.Logan@Sun.COM 		break;
671*9663SMark.Logan@Sun.COM 	case GNOME_VFS_SEEK_END:
672*9663SMark.Logan@Sun.COM 		/* FIXME: NOT IMPLEMENTED YET */
673*9663SMark.Logan@Sun.COM 		g_return_val_if_reached(GNOME_VFS_ERROR_BAD_PARAMETERS);
674*9663SMark.Logan@Sun.COM 	default:
675*9663SMark.Logan@Sun.COM 		g_assert_not_reached();
676*9663SMark.Logan@Sun.COM 	}
677*9663SMark.Logan@Sun.COM 
678*9663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
679*9663SMark.Logan@Sun.COM }
680*9663SMark.Logan@Sun.COM 
681*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_tell(GnomeVFSMethod *method,
682*9663SMark.Logan@Sun.COM 		GnomeVFSMethodHandle *method_handle,
683*9663SMark.Logan@Sun.COM 		GnomeVFSFileSize *offset_return)
684*9663SMark.Logan@Sun.COM {
685*9663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
686*9663SMark.Logan@Sun.COM 	struct libntfs_file *libntfs_file;
687*9663SMark.Logan@Sun.COM 
688*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
689*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
690*9663SMark.Logan@Sun.COM 	libntfs_file = (struct libntfs_file *)method_handle;
691*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file != NULL,
692*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
693*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(offset_return != NULL,
694*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
695*9663SMark.Logan@Sun.COM 
696*9663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult = libntfs_open_attr(libntfs_file)))
697*9663SMark.Logan@Sun.COM 		return errvfsresult;
698*9663SMark.Logan@Sun.COM 
699*9663SMark.Logan@Sun.COM 	*offset_return = libntfs_file->pos;
700*9663SMark.Logan@Sun.COM 	g_assert((s64)*offset_return == libntfs_file->pos);
701*9663SMark.Logan@Sun.COM 
702*9663SMark.Logan@Sun.COM 	return errvfsresult;
703*9663SMark.Logan@Sun.COM }
704*9663SMark.Logan@Sun.COM 
705*9663SMark.Logan@Sun.COM static gboolean libntfs_gnomevfs_is_local(GnomeVFSMethod *method,
706*9663SMark.Logan@Sun.COM 		const GnomeVFSURI *uri)
707*9663SMark.Logan@Sun.COM {
708*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
709*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
710*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(uri != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
711*9663SMark.Logan@Sun.COM 
712*9663SMark.Logan@Sun.COM 	return gnome_vfs_uri_is_local(uri->parent);
713*9663SMark.Logan@Sun.COM }
714*9663SMark.Logan@Sun.COM 
715*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_get_file_info_from_handle(
716*9663SMark.Logan@Sun.COM 		GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle,
717*9663SMark.Logan@Sun.COM 		GnomeVFSFileInfo *file_info,
718*9663SMark.Logan@Sun.COM 		GnomeVFSFileInfoOptions options __attribute__((unused)),
719*9663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
720*9663SMark.Logan@Sun.COM {
721*9663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
722*9663SMark.Logan@Sun.COM 	struct libntfs_file *libntfs_file;
723*9663SMark.Logan@Sun.COM 
724*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
725*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
726*9663SMark.Logan@Sun.COM 	libntfs_file = (struct libntfs_file *)method_handle;
727*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(libntfs_file != NULL,
728*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
729*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(file_info != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
730*9663SMark.Logan@Sun.COM 	/* handle 'options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE'? */
731*9663SMark.Logan@Sun.COM 
732*9663SMark.Logan@Sun.COM 	file_info->valid_fields = 0;
733*9663SMark.Logan@Sun.COM 	/* FIXME: It is complicated to read filename of open 'ntfs_inode'. */
734*9663SMark.Logan@Sun.COM 	file_info->name = NULL;
735*9663SMark.Logan@Sun.COM 
736*9663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult = libntfs_open_attr(libntfs_file))) {
737*9663SMark.Logan@Sun.COM 		/* Assume we are directory: */
738*9663SMark.Logan@Sun.COM 		file_info->type = GNOME_VFS_FILE_TYPE_DIRECTORY;
739*9663SMark.Logan@Sun.COM 		/*
740*9663SMark.Logan@Sun.COM 		 * Do not: file_info->valid_fields |=
741*9663SMark.Logan@Sun.COM 		 * GNOME_VFS_FILE_INFO_FIELDS_TYPE;
742*9663SMark.Logan@Sun.COM 		 * as gnome-vfs-xfer.c/copy_items() does not check
743*9663SMark.Logan@Sun.COM 		 * 'GNOME_VFS_FILE_INFO_FIELDS_TYPE' and we are just bluffing
744*9663SMark.Logan@Sun.COM 		 * we know it.
745*9663SMark.Logan@Sun.COM 		 */
746*9663SMark.Logan@Sun.COM 		return GNOME_VFS_OK;
747*9663SMark.Logan@Sun.COM 	}
748*9663SMark.Logan@Sun.COM 
749*9663SMark.Logan@Sun.COM 	/* FIXME: Is 'data_size' the right field? */
750*9663SMark.Logan@Sun.COM 	file_info->size = libntfs_file->attr->data_size;
751*9663SMark.Logan@Sun.COM 	file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_SIZE;
752*9663SMark.Logan@Sun.COM 
753*9663SMark.Logan@Sun.COM 	/*
754*9663SMark.Logan@Sun.COM 	 * FIXME: We do not really know the type of 'libntfs_file' but
755*9663SMark.Logan@Sun.COM 	 * gnome-vfs-xfer.c/copy_items() requires 'GNOME_VFS_FILE_TYPE_REGULAR'
756*9663SMark.Logan@Sun.COM 	 * to copy it.
757*9663SMark.Logan@Sun.COM 	 */
758*9663SMark.Logan@Sun.COM 	file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
759*9663SMark.Logan@Sun.COM 	/*
760*9663SMark.Logan@Sun.COM 	 * Do not: file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE;
761*9663SMark.Logan@Sun.COM 	 * as gnome-vfs-xfer.c/copy_items() does not check
762*9663SMark.Logan@Sun.COM 	 * 'GNOME_VFS_FILE_INFO_FIELDS_TYPE' and we are just bluffing we know
763*9663SMark.Logan@Sun.COM 	 * it.
764*9663SMark.Logan@Sun.COM 	 */
765*9663SMark.Logan@Sun.COM 
766*9663SMark.Logan@Sun.COM 	return errvfsresult;
767*9663SMark.Logan@Sun.COM }
768*9663SMark.Logan@Sun.COM 
769*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_get_file_info(GnomeVFSMethod *method,
770*9663SMark.Logan@Sun.COM 		GnomeVFSURI *uri, GnomeVFSFileInfo *file_info,
771*9663SMark.Logan@Sun.COM 		GnomeVFSFileInfoOptions options, GnomeVFSContext *context)
772*9663SMark.Logan@Sun.COM {
773*9663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
774*9663SMark.Logan@Sun.COM 	GnomeVFSMethodHandle *method_handle;
775*9663SMark.Logan@Sun.COM 
776*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
777*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
778*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(file_info != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
779*9663SMark.Logan@Sun.COM 	/* handle 'options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE'? */
780*9663SMark.Logan@Sun.COM 
781*9663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
782*9663SMark.Logan@Sun.COM 			libntfs_gnomevfs_open(method, &method_handle, uri,
783*9663SMark.Logan@Sun.COM 			GNOME_VFS_OPEN_READ, context)))
784*9663SMark.Logan@Sun.COM 		return errvfsresult;
785*9663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
786*9663SMark.Logan@Sun.COM 			libntfs_gnomevfs_get_file_info_from_handle(method,
787*9663SMark.Logan@Sun.COM 			method_handle, file_info, options, context)))
788*9663SMark.Logan@Sun.COM 		return errvfsresult;
789*9663SMark.Logan@Sun.COM 	if (GNOME_VFS_OK != (errvfsresult =
790*9663SMark.Logan@Sun.COM 			libntfs_gnomevfs_close(method, method_handle, context)))
791*9663SMark.Logan@Sun.COM 		return errvfsresult;
792*9663SMark.Logan@Sun.COM 
793*9663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
794*9663SMark.Logan@Sun.COM }
795*9663SMark.Logan@Sun.COM 
796*9663SMark.Logan@Sun.COM static GnomeVFSResult libntfs_gnomevfs_check_same_fs(GnomeVFSMethod *method,
797*9663SMark.Logan@Sun.COM 		GnomeVFSURI *a, GnomeVFSURI *b, gboolean *same_fs_return,
798*9663SMark.Logan@Sun.COM 		GnomeVFSContext *context __attribute__((unused)))
799*9663SMark.Logan@Sun.COM {
800*9663SMark.Logan@Sun.COM 	ntfs_volume *volume_a;
801*9663SMark.Logan@Sun.COM 	ntfs_volume *volume_b;
802*9663SMark.Logan@Sun.COM 	GnomeVFSResult errvfsresult;
803*9663SMark.Logan@Sun.COM 
804*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method == &GnomeVFSMethod_static,
805*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
806*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(same_fs_return != NULL,
807*9663SMark.Logan@Sun.COM 			GNOME_VFS_ERROR_BAD_PARAMETERS);
808*9663SMark.Logan@Sun.COM 
809*9663SMark.Logan@Sun.COM 	errvfsresult = libntfs_gnomevfs_uri_parent_init(&volume_a, a);
810*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(errvfsresult == GNOME_VFS_OK, errvfsresult);
811*9663SMark.Logan@Sun.COM 
812*9663SMark.Logan@Sun.COM 	errvfsresult = libntfs_gnomevfs_uri_parent_init(&volume_b, b);
813*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(errvfsresult == GNOME_VFS_OK, errvfsresult);
814*9663SMark.Logan@Sun.COM 
815*9663SMark.Logan@Sun.COM 	*same_fs_return = (volume_a == volume_b);
816*9663SMark.Logan@Sun.COM 
817*9663SMark.Logan@Sun.COM 	return GNOME_VFS_OK;
818*9663SMark.Logan@Sun.COM }
819*9663SMark.Logan@Sun.COM 
820*9663SMark.Logan@Sun.COM /**
821*9663SMark.Logan@Sun.COM  * libntfs_gnomevfs_init:
822*9663SMark.Logan@Sun.COM  *
823*9663SMark.Logan@Sun.COM  * Returns: Initialized structure of #GnomeVFSMethod with static methods of
824*9663SMark.Logan@Sun.COM  * libntfs-gnomevfs.
825*9663SMark.Logan@Sun.COM  */
826*9663SMark.Logan@Sun.COM GnomeVFSMethod *libntfs_gnomevfs_method_init(const gchar *method_name,
827*9663SMark.Logan@Sun.COM 		const gchar *args)
828*9663SMark.Logan@Sun.COM {
829*9663SMark.Logan@Sun.COM 	struct method_name_info *method_name_info;
830*9663SMark.Logan@Sun.COM 
831*9663SMark.Logan@Sun.COM 	g_return_val_if_fail(method_name != NULL, NULL);
832*9663SMark.Logan@Sun.COM 	/* 'args' may be NULL if not supplied. */
833*9663SMark.Logan@Sun.COM 
834*9663SMark.Logan@Sun.COM 	method_name_hash_init();
835*9663SMark.Logan@Sun.COM 
836*9663SMark.Logan@Sun.COM 	G_LOCK(method_name_hash);
837*9663SMark.Logan@Sun.COM 	method_name_info = g_hash_table_lookup(method_name_hash, method_name);
838*9663SMark.Logan@Sun.COM 	if (method_name_info && strcmp(method_name_info->args, args))
839*9663SMark.Logan@Sun.COM 		method_name_info = NULL;
840*9663SMark.Logan@Sun.COM 	G_UNLOCK(method_name_hash);
841*9663SMark.Logan@Sun.COM 	if (!method_name_info) {
842*9663SMark.Logan@Sun.COM 
843*9663SMark.Logan@Sun.COM #ifdef __sun
844*9663SMark.Logan@Sun.COM 		method_name_info = g_new(struct method_name_info, 1);
845*9663SMark.Logan@Sun.COM #else /* !__sun */
846*9663SMark.Logan@Sun.COM 		libntfs_new(method_name_info);
847*9663SMark.Logan@Sun.COM #endif /* __sun */
848*9663SMark.Logan@Sun.COM 
849*9663SMark.Logan@Sun.COM 		method_name_info->args = g_strdup(args);
850*9663SMark.Logan@Sun.COM 		G_LOCK(method_name_hash);
851*9663SMark.Logan@Sun.COM 		g_hash_table_replace(method_name_hash, g_strdup(method_name),
852*9663SMark.Logan@Sun.COM 				method_name_info);
853*9663SMark.Logan@Sun.COM 		G_UNLOCK(method_name_hash);
854*9663SMark.Logan@Sun.COM 	}
855*9663SMark.Logan@Sun.COM 
856*9663SMark.Logan@Sun.COM 	G_LOCK(GnomeVFSMethod_static);
857*9663SMark.Logan@Sun.COM 	LIBNTFS_MEMZERO(&GnomeVFSMethod_static);
858*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.method_table_size = sizeof(GnomeVFSMethod_static);
859*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.open = libntfs_gnomevfs_open;	/* mandatory */
860*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.create = libntfs_gnomevfs_create;	/* mandatory */
861*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.close = libntfs_gnomevfs_close;
862*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.read = libntfs_gnomevfs_read;
863*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.seek = libntfs_gnomevfs_seek;
864*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.tell = libntfs_gnomevfs_tell;
865*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.open_directory = libntfs_gnomevfs_open_directory;
866*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.close_directory =
867*9663SMark.Logan@Sun.COM 			libntfs_gnomevfs_close_directory;
868*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.read_directory = libntfs_gnomevfs_read_directory;
869*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.get_file_info =
870*9663SMark.Logan@Sun.COM 			libntfs_gnomevfs_get_file_info;	/* mandatory */
871*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.get_file_info_from_handle =
872*9663SMark.Logan@Sun.COM 			libntfs_gnomevfs_get_file_info_from_handle;
873*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.is_local =
874*9663SMark.Logan@Sun.COM 			libntfs_gnomevfs_is_local;	/* mandatory */
875*9663SMark.Logan@Sun.COM 	GnomeVFSMethod_static.check_same_fs = libntfs_gnomevfs_check_same_fs;
876*9663SMark.Logan@Sun.COM 	/* TODO: GnomeVFSMethodFindDirectoryFunc find_directory; */
877*9663SMark.Logan@Sun.COM 	/* TODO: GnomeVFSMethodFileControlFunc file_control; */
878*9663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethodCreateSymbolicLinkFunc create_symbolic_link; */
879*9663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethodMonitorAddFunc monitor_add; */
880*9663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethodMonitorCancelFunc monitor_cancel; */
881*9663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.write; */
882*9663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.truncate_handle; */
883*9663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.make_directory; */
884*9663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.remove_directory; */
885*9663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.move; */
886*9663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.unlink; */
887*9663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.set_file_info; */
888*9663SMark.Logan@Sun.COM 	/* R/W:  GnomeVFSMethod_static.truncate; */
889*9663SMark.Logan@Sun.COM 	G_UNLOCK(GnomeVFSMethod_static);
890*9663SMark.Logan@Sun.COM 
891*9663SMark.Logan@Sun.COM 	return &GnomeVFSMethod_static;
892*9663SMark.Logan@Sun.COM }
893*9663SMark.Logan@Sun.COM 
894*9663SMark.Logan@Sun.COM /**
895*9663SMark.Logan@Sun.COM  * libntfs_gnomevfs_method_shutdown:
896*9663SMark.Logan@Sun.COM  *
897*9663SMark.Logan@Sun.COM  * Shutdowns libntfs-gnomevfs successfuly flushing all caches.
898*9663SMark.Logan@Sun.COM  *
899*9663SMark.Logan@Sun.COM  * Sad note about gnome-vfs-2.1.5 is that it never calls this function. :-)
900*9663SMark.Logan@Sun.COM  */
901*9663SMark.Logan@Sun.COM void libntfs_gnomevfs_method_shutdown(void)
902*9663SMark.Logan@Sun.COM {
903*9663SMark.Logan@Sun.COM 	uri_parent_string_hash_init();
904*9663SMark.Logan@Sun.COM 	G_LOCK(uri_parent_string_hash);
905*9663SMark.Logan@Sun.COM 	g_hash_table_destroy(uri_parent_string_hash);
906*9663SMark.Logan@Sun.COM 	uri_parent_string_hash = NULL;
907*9663SMark.Logan@Sun.COM 	G_UNLOCK(uri_parent_string_hash);
908*9663SMark.Logan@Sun.COM 
909*9663SMark.Logan@Sun.COM 	method_name_hash_init();
910*9663SMark.Logan@Sun.COM 	G_LOCK(method_name_hash);
911*9663SMark.Logan@Sun.COM 	g_hash_table_destroy(method_name_hash);
912*9663SMark.Logan@Sun.COM 	method_name_hash = NULL;
913*9663SMark.Logan@Sun.COM 	G_UNLOCK(method_name_hash);
914*9663SMark.Logan@Sun.COM }
915*9663SMark.Logan@Sun.COM 
916