+Report 'file size' for regular files during read_directory().
[ntfsprogs-gnomevfs.git] / src / gnome-vfs-method.c
index 21e97c2..fbd4b13 100644 (file)
@@ -31,6 +31,7 @@
 #include "gnome-vfs-module.h"
 #include <glib/ghash.h>
 #include <string.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
 
 #include <ntfs/volume.h>
 #include <ntfs/dir.h>
@@ -182,6 +183,7 @@ int errint;
        mref=FILE_root;
        for (;;) {
 uchar_t *pathname_parse_ucs2;
+gchar *pathname_parse_unescaped;
 int i;
 
                G_LOCK(libntfs);
@@ -199,10 +201,13 @@ int i;
                while (*pathname_next==G_DIR_SEPARATOR)
                        pathname_next++;
                /* FIXME: Is 'pathname' utf8? */
-               libntfs_newn(pathname_parse_ucs2,strlen(pathname_parse)+1);
-               for (i=0;pathname_parse[i];i++)
-                       pathname_parse_ucs2[i]=pathname_parse[i];
+               pathname_parse_unescaped=gnome_vfs_unescape_string(pathname_parse,
+                               NULL);  /* illegal_characters */
+               libntfs_newn(pathname_parse_ucs2,strlen(pathname_parse_unescaped)+1);
+               for (i=0;pathname_parse_unescaped[i];i++)
+                       pathname_parse_ucs2[i]=pathname_parse_unescaped[i];
                pathname_parse_ucs2[i]=0;
+               g_free(pathname_parse_unescaped);
                G_LOCK(libntfs);
                mref=ntfs_inode_lookup_by_name(inode,pathname_parse_ucs2,i);
                G_UNLOCK(libntfs);
@@ -236,8 +241,8 @@ struct libntfs_directory *libntfs_directory;
        g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
        g_return_val_if_fail(method_handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
 
-       errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume,uri);
-       g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
+       if (GNOME_VFS_OK!=(errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume,uri)))
+               return errvfsresult;
 
        if (GNOME_VFS_OK!=(errvfsresult=inode_open_by_pathname(&inode,volume,uri->text)))
                return errvfsresult;
@@ -267,7 +272,17 @@ int errint;
        if (errint)
                g_return_val_if_reached(GNOME_VFS_ERROR_INTERNAL);
 
-       gnome_vfs_file_info_list_free(libntfs_directory->file_info_list);
+       if (libntfs_directory->file_info_list) {
+GList *last_l;
+
+               /* Prevent gnome_vfs_file_info_list_free() and its gnome_vfs_file_info_unref()
+                * on the last 'file_info_list' items as it is EOF with NULL '->data'.
+                */
+               last_l=g_list_last(libntfs_directory->file_info_list);
+               g_assert(last_l->data==NULL);
+               libntfs_directory->file_info_list=g_list_delete_link(libntfs_directory->file_info_list,last_l);
+               gnome_vfs_file_info_list_free(libntfs_directory->file_info_list);
+               }
 
        g_free(libntfs_directory);
 
@@ -287,6 +302,9 @@ int i;
                        FALSE); /* free_segment */
 }
 
+/* Do not lock 'libntfs' here as we are already locked
+ * inside ntfs_readdir().
+ */
 static int libntfs_gnomevfs_read_directory_filldir(struct libntfs_directory *libntfs_directory /* dirent */,
                const uchar_t *name,const int name_len,const int name_type,const s64 pos,const MFT_REF mref,const unsigned dt_type)
 {
@@ -297,6 +315,9 @@ GnomeVFSFileInfo *file_info;
        g_return_val_if_fail(name_len>=0,-1);
        g_return_val_if_fail(pos>=0,-1);
 
+       if (name_len>0 && name[0]=='$') /* system directory; FIXME: What is its proper identification? */
+               return 0;       /* continue traversal */
+
        file_info=gnome_vfs_file_info_new();
        file_info->name=libntfs_uchar_to_utf8(name,name_len);
        file_info->valid_fields=0;
@@ -315,6 +336,32 @@ GnomeVFSFileInfo *file_info;
        if (file_info->type!=GNOME_VFS_FILE_TYPE_UNKNOWN)
                file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE;
 
+       /* Detect 'file_info->size': */
+       if (file_info->type==GNOME_VFS_FILE_TYPE_REGULAR) {
+ntfs_inode *inode;
+
+               inode=ntfs_inode_open(libntfs_directory->inode->vol,mref);
+               /* FIXME: Check failed 'inode' open. */
+               if (inode) {
+ntfs_attr *attr;
+int errint;
+
+                       attr=ntfs_attr_open(
+                                       inode,  /* ni */
+                                       AT_DATA,        /* type */
+                                       NULL,   /* name */
+                                       0);     /* name_len */
+                       /* FIXME: Check failed 'attr' open. */
+                       if (attr) {
+                               file_info->size=attr->data_size;        /* FIXME: Is 'data_size' the right field? */
+                               file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_SIZE;
+                               ntfs_attr_close(attr);
+                               }
+                       errint=ntfs_inode_close(inode);
+                       /* FIXME: Check 'errint'. */
+                       }
+               }
+
        libntfs_directory->file_info_list=g_list_prepend(libntfs_directory->file_info_list,file_info);
 
        return 0;       /* continue traversal */
@@ -407,8 +454,8 @@ struct libntfs_file *libntfs_file;
        g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
        g_return_val_if_fail(method_handle_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
 
-       errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume,uri);
-       g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
+       if (GNOME_VFS_OK!=(errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume,uri)))
+               return errvfsresult;
 
        if (mode & GNOME_VFS_OPEN_WRITE)
                return GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM;
@@ -435,8 +482,8 @@ ntfs_volume *volume;
        g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
        g_return_val_if_fail(method_handle_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
 
-       errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume,uri);
-       g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
+       if (GNOME_VFS_OK!=(errvfsresult=libntfs_gnomevfs_uri_parent_init(&volume,uri)))
+               return errvfsresult;
 
        return GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM;
 }
@@ -571,12 +618,19 @@ struct libntfs_file *libntfs_file;
        g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
        /* handle 'options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE'? */
 
-       if (GNOME_VFS_OK!=(errvfsresult=libntfs_open_attr(libntfs_file)))
-               return errvfsresult;
-
        file_info->valid_fields=0;
        file_info->name=NULL;   /* FIXME: It is complicated to read filename of open 'ntfs_inode'. */
 
+       if (GNOME_VFS_OK!=(errvfsresult=libntfs_open_attr(libntfs_file))) {
+               /* Assume we are directory: */
+               file_info->type=GNOME_VFS_FILE_TYPE_DIRECTORY;
+               /* Do not: file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE;
+                * as gnome-vfs-xfer.c/copy_items() does not check 'GNOME_VFS_FILE_INFO_FIELDS_TYPE'
+                * and we are just bluffing we know it.
+                */
+               return GNOME_VFS_OK;
+               }
+
        file_info->size=libntfs_file->attr->data_size;  /* FIXME: Is 'data_size' the right field? */
        file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_SIZE;