+captive_gnomevfs_close()
authorshort <>
Mon, 23 Dec 2002 00:08:19 +0000 (00:08 +0000)
committershort <>
Mon, 23 Dec 2002 00:08:19 +0000 (00:08 +0000)
+captive_gnomevfs_read()
+captive_gnomevfs_seek()
+captive_gnomevfs_tell()
+handling of STATUS_OBJECT_NAME_NOT_FOUND (->GNOME_VFS_ERROR_NOT_FOUND)
Fixed accessibility of directories: +=GNOME_VFS_PERM_USER_EXEC
Fixed 'uri->text' decoding - used gnome_vfs_unescape_string()

src/client/libcaptive-gnomevfs/gnome-vfs-method.c

index ebe523f..ed26d6b 100644 (file)
@@ -30,6 +30,7 @@
 #include "captive/unicode.h"
 #include "reactos/ddk/iofuncs.h"       /* for IoCreateFile() */
 #include "gnome-vfs-module.h"
+#include <libgnomevfs/gnome-vfs-utils.h>       /* for gnome_vfs_unescape_string() */
 
 
 static GnomeVFSMethod GnomeVFSMethod_static;
@@ -49,7 +50,7 @@ static GnomeVFSResult captive_gnomevfs_uri_parent_init(GnomeVFSURI *uri,OBJECT_A
 {
 gchar *uri_parent_string;
 GnomeVFSResult errvfsresult;
-gchar *w32_path,*s,*d;
+gchar *w32_path,*s,*d,*vfs_path;
 
        g_return_val_if_fail(uri!=NULL,GNOME_VFS_ERROR_INVALID_URI);
 
@@ -85,8 +86,12 @@ gchar *w32_path,*s,*d;
                 * On the other side it will somehow get managed automatically and it works even
                 * without the trailing "\\." for root directory open - don't ask me why. :-)
                 */
+               vfs_path=gnome_vfs_unescape_string(     /* decode %xy escaping */
+                               uri->text,      /* escaped */
+                               NULL);  /* illegal_characters */
                w32_path=(gchar *)/* de-const it as we can modify it but we must not free() it */
-                               captive_printf_alloca("\\Device\\CdRom0\\%s",uri->text);
+                               captive_printf_alloca("\\Device\\CdRom0\\%s",vfs_path);
+               g_free(vfs_path);
                /* translate '/' -> '\' */
                for (s=w32_path;(s=strchr(s,'/'));s++)
                        *s='\\';
@@ -162,8 +167,8 @@ struct captive_gnomevfs_directory_handle *directory_handle;
                        0);     /* Options */
        G_UNLOCK(libcaptive);
        g_free(dir_ObjectAttributes.ObjectName);        /* left from captive_gnomevfs_uri_parent_init() */
+       g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(dir_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
        g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
-       g_return_val_if_fail(NT_SUCCESS(dir_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
        g_return_val_if_fail(dir_IoStatusBlock.Information==FILE_OPENED,GNOME_VFS_ERROR_GENERIC);
 
        captive_new(directory_handle);
@@ -241,6 +246,8 @@ ULONG tmp_ULONG;
 
        /* we use 0600 for r/w files, 0400 for FILE_ATTRIBUTE_READONLY */
        file_info->permissions=GNOME_VFS_PERM_USER_READ;
+       if (file_info->type==GNOME_VFS_FILE_TYPE_DIRECTORY)
+               file_info->permissions|=GNOME_VFS_PERM_USER_EXEC;
        if (!(FileIdBothDirInformation->FileAttributes & FILE_ATTRIBUTE_READONLY))
                file_info->permissions=GNOME_VFS_PERM_USER_WRITE;
        file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
@@ -328,10 +335,174 @@ GnomeVFSResult errvfsresult;
 }
 
 
+struct captive_gnomevfs_file_handle {
+       HANDLE file_Handle;
+       GnomeVFSFileOffset offset;
+       };
+
 static GnomeVFSResult captive_gnomevfs_open(GnomeVFSMethod *method,
                GnomeVFSMethodHandle **method_handle_return,GnomeVFSURI *uri,GnomeVFSOpenMode mode,GnomeVFSContext *context)
 {
-       g_return_val_if_reached(GNOME_VFS_ERROR_NOT_SUPPORTED); /* FIXME: NOT IMPLEMENTED YET */
+IO_STATUS_BLOCK file_IoStatusBlock;
+GnomeVFSResult errvfsresult;
+OBJECT_ATTRIBUTES file_ObjectAttributes;
+HANDLE file_Handle;
+struct captive_gnomevfs_file_handle *file_handle;
+NTSTATUS err;
+
+       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);
+
+       /* init */
+       errvfsresult=captive_gnomevfs_uri_parent_init(uri,&file_ObjectAttributes);
+       g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
+       
+       /* open */
+       G_LOCK(libcaptive);
+       err=IoCreateFile(
+                       &file_Handle,   /* FileHandle */
+                       0
+                                       |(!(mode&GNOME_VFS_OPEN_READ ) ? 0 : FILE_READ_DATA)
+                                       |(!(mode&GNOME_VFS_OPEN_WRITE) ? 0 : FILE_WRITE_DATA | FILE_APPEND_DATA)
+                                       ,       /* DesiredAccess */
+                       &file_ObjectAttributes, /* ObjectAttributes */
+                       &file_IoStatusBlock,    /* IoStatusBlock */
+                       NULL,   /* AllocationSize; ignored for open */
+                       FILE_ATTRIBUTE_NORMAL,  /* FileAttributes; ignored for open */
+                       FILE_SHARE_WRITE,       /* ShareAccess; 0 means exclusive */
+                       FILE_OPEN,      /* CreateDisposition */
+                       /* FILE_SYNCHRONOUS_IO_{,NON}ALERT: We need to allow W32 filesystem
+                                * any waits to not to let it return STATUS_CANT_WAIT us.
+                                * Alertability should have only effect on asynchronous events
+                                * from KeWaitForSingleObject() by setting/clearing its parameter 'Alertable'.
+                                */
+                       FILE_SYNCHRONOUS_IO_ALERT,      /* CreateOptions */
+                       NULL,   /* EaBuffer */
+                       0,      /* EaLength */
+                       CreateFileTypeNone,     /* CreateFileType */
+                       NULL,   /* ExtraCreateParameters */
+                       0);     /* Options */
+       G_UNLOCK(libcaptive);
+       g_free(file_ObjectAttributes.ObjectName);       /* left from captive_gnomevfs_uri_parent_init() */
+       g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
+       g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
+       g_return_val_if_fail(file_IoStatusBlock.Information==FILE_OPENED,GNOME_VFS_ERROR_GENERIC);
+
+       captive_new(file_handle);
+       file_handle->file_Handle=file_Handle;
+       file_handle->offset=0;
+
+       *method_handle_return=(GnomeVFSMethodHandle *)file_handle;
+       return GNOME_VFS_OK;
+}
+
+
+static GnomeVFSResult captive_gnomevfs_close(GnomeVFSMethod *method,
+               GnomeVFSMethodHandle *method_handle,GnomeVFSContext *context)
+{
+struct captive_gnomevfs_file_handle *file_handle;
+NTSTATUS err;
+
+       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);
+
+       file_handle=(struct captive_gnomevfs_file_handle *)method_handle;
+       G_LOCK(libcaptive);
+       err=NtClose(file_handle->file_Handle);
+       G_UNLOCK(libcaptive);
+       g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
+
+       g_free(file_handle);
+       return GNOME_VFS_OK;
+}
+
+
+static GnomeVFSResult captive_gnomevfs_read(GnomeVFSMethod *method,GnomeVFSMethodHandle *method_handle,
+               gpointer buffer,GnomeVFSFileSize num_bytes,GnomeVFSFileSize *bytes_read_return,GnomeVFSContext *context)
+{
+struct captive_gnomevfs_file_handle *file_handle;
+NTSTATUS err;
+IO_STATUS_BLOCK file_IoStatusBlock;
+LARGE_INTEGER file_offset;
+
+       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);
+       g_return_val_if_fail(buffer!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+       g_return_val_if_fail(bytes_read_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+       g_return_val_if_fail(num_bytes==(ULONG)num_bytes,GNOME_VFS_ERROR_BAD_PARAMETERS);
+
+       file_handle=(struct captive_gnomevfs_file_handle *)method_handle;
+       file_offset.QuadPart=file_handle->offset;
+       G_LOCK(libcaptive);
+       err=NtReadFile(
+                       file_handle->file_Handle,       /* FileHandle */
+                       NULL,   /* EventHandle; completion signalling; optional */
+                       NULL,   /* ApcRoutine; optional */
+                       NULL,   /* ApcContext; optional */
+                       &file_IoStatusBlock,    /* IoStatusBlock */
+                       buffer, /* Buffer */
+                       num_bytes,      /* Length */
+                       &file_offset,   /* ByteOffset */
+                       NULL);  /* Key; NULL means no file locking key */
+       G_UNLOCK(libcaptive);
+       if (err==STATUS_END_OF_FILE) {
+               g_return_val_if_fail(file_IoStatusBlock.Status==STATUS_END_OF_FILE,GNOME_VFS_ERROR_GENERIC);
+               g_return_val_if_fail(file_IoStatusBlock.Information==0,GNOME_VFS_ERROR_GENERIC);
+               *bytes_read_return=0;
+               return GNOME_VFS_ERROR_EOF;
+               }
+       g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
+       g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
+       g_return_val_if_fail(file_IoStatusBlock.Information<=num_bytes,GNOME_VFS_ERROR_GENERIC);
+
+       file_handle->offset+=file_IoStatusBlock.Information;
+       *bytes_read_return=file_IoStatusBlock.Information;
+       return GNOME_VFS_OK;
+}
+
+
+static GnomeVFSResult captive_gnomevfs_seek(GnomeVFSMethod *method,
+               GnomeVFSMethodHandle *method_handle,GnomeVFSSeekPosition whence,GnomeVFSFileOffset offset,GnomeVFSContext *context)
+{
+struct captive_gnomevfs_file_handle *file_handle;
+
+       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);
+
+       file_handle=(struct captive_gnomevfs_file_handle *)method_handle;
+       switch (whence) {
+               case GNOME_VFS_SEEK_START:
+                       file_handle->offset=offset;
+                       break;
+               case GNOME_VFS_SEEK_CURRENT:
+                       if (0
+                                       || (offset>0 && (file_handle->offset+offset)<file_handle->offset)
+                                       || (offset<0 && (file_handle->offset+offset)>file_handle->offset))
+                               return GNOME_VFS_ERROR_BAD_PARAMETERS;
+                       file_handle->offset+=offset;
+                       break;
+               case GNOME_VFS_SEEK_END:
+                       g_assert_not_reached(); /* NOT IMPLEMENTED YET */
+                       break;
+               default:
+                       g_return_val_if_reached(GNOME_VFS_ERROR_BAD_PARAMETERS);
+               }
+
+       return GNOME_VFS_OK;
+}
+
+static GnomeVFSResult captive_gnomevfs_tell(GnomeVFSMethod *method,
+               GnomeVFSMethodHandle *method_handle,GnomeVFSFileOffset *offset_return)
+{
+struct captive_gnomevfs_file_handle *file_handle;
+
+       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);
+       g_return_val_if_fail(offset_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+
+       file_handle=(struct captive_gnomevfs_file_handle *)method_handle;
+       *offset_return=file_handle->offset;
+       return GNOME_VFS_OK;
 }
 
 
@@ -348,7 +519,7 @@ static gboolean captive_gnomevfs_is_local(GnomeVFSMethod *method,const GnomeVFSU
        g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS);
        g_return_val_if_fail(uri!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
 
-       return gnome_vfs_uri_is_local (uri->parent);
+       return gnome_vfs_uri_is_local(uri->parent);
 }
 
 
@@ -396,6 +567,8 @@ ULONG tmp_ULONG;
 
        /* we use 0600 for r/w files, 0400 for FILE_ATTRIBUTE_READONLY */
        file_info->permissions=GNOME_VFS_PERM_USER_READ;
+       if (file_info->type==GNOME_VFS_FILE_TYPE_DIRECTORY)
+               file_info->permissions|=GNOME_VFS_PERM_USER_EXEC;
        if (!(FileAllInformationStruct->BasicInformation.FileAttributes & FILE_ATTRIBUTE_READONLY))
                file_info->permissions=GNOME_VFS_PERM_USER_WRITE;
        file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
@@ -483,8 +656,10 @@ char QueryFile_buf[sizeof(FILE_ALL_INFORMATION)
                        0);     /* Options */
        G_UNLOCK(libcaptive);
        g_free(file_ObjectAttributes.ObjectName);       /* left from captive_gnomevfs_uri_parent_init() */
+       g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
+       if (err==STATUS_OBJECT_NAME_NOT_FOUND)
+               return GNOME_VFS_ERROR_NOT_FOUND;
        g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
-       g_return_val_if_fail(NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
        g_return_val_if_fail(file_IoStatusBlock.Information==FILE_OPENED,GNOME_VFS_ERROR_GENERIC);
 
        /* query */
@@ -544,6 +719,10 @@ GnomeVFSMethod *captive_gnomevfs_method_init(const gchar *fs_path)
        GnomeVFSMethod_static.close_directory=captive_gnomevfs_close_directory;
        GnomeVFSMethod_static.read_directory =captive_gnomevfs_read_directory;
        GnomeVFSMethod_static.open           =captive_gnomevfs_open;    /* mandatory */
+       GnomeVFSMethod_static.close          =captive_gnomevfs_close;
+       GnomeVFSMethod_static.read           =captive_gnomevfs_read;
+       GnomeVFSMethod_static.seek           =captive_gnomevfs_seek;
+       GnomeVFSMethod_static.tell           =captive_gnomevfs_tell;
        GnomeVFSMethod_static.create         =captive_gnomevfs_create;  /* mandatory */
        GnomeVFSMethod_static.is_local       =captive_gnomevfs_is_local;        /* mandatory */
        GnomeVFSMethod_static.get_file_info  =captive_gnomevfs_get_file_info;   /* mandatory */