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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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