Alexandre Julliard : server: Store a duplicate of the file descriptor for file mappings.

Alexandre Julliard julliard at winehq.org
Tue Nov 24 12:40:20 CST 2009


Module: wine
Branch: master
Commit: 5f808f03e1bc379fb02eaf4b16a43247410c7003
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5f808f03e1bc379fb02eaf4b16a43247410c7003

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Nov 23 16:16:46 2009 +0100

server: Store a duplicate of the file descriptor for file mappings.

---

 server/fd.c      |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 server/file.h    |    4 +++
 server/mapping.c |   30 +++++++++++++++++++++++-
 3 files changed, 97 insertions(+), 2 deletions(-)

diff --git a/server/fd.c b/server/fd.c
index f57ed97..a4018ee 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1488,6 +1488,59 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
     return fd;
 }
 
+/* duplicate an fd object for a different user */
+struct fd *dup_fd_object( struct fd *orig )
+{
+    struct fd *fd = alloc_object( &fd_ops );
+
+    if (!fd) return NULL;
+
+    fd->fd_ops     = NULL;
+    fd->user       = NULL;
+    fd->inode      = NULL;
+    fd->closed     = NULL;
+    fd->access     = orig->access;
+    fd->options    = orig->options;
+    fd->sharing    = orig->sharing;
+    fd->unix_fd    = -1;
+    fd->signaled   = 0;
+    fd->fs_locks   = 0;
+    fd->poll_index = -1;
+    fd->read_q     = NULL;
+    fd->write_q    = NULL;
+    fd->wait_q     = NULL;
+    fd->completion = NULL;
+    list_init( &fd->inode_entry );
+    list_init( &fd->locks );
+
+    if (!(fd->unix_name = mem_alloc( strlen(orig->unix_name) + 1 ))) goto failed;
+    strcpy( fd->unix_name, orig->unix_name );
+    if ((fd->poll_index = add_poll_user( fd )) == -1) goto failed;
+
+    if (orig->inode)
+    {
+        struct closed_fd *closed = mem_alloc( sizeof(*closed) );
+        if (!closed) goto failed;
+        if ((fd->unix_fd = dup( orig->unix_fd )) == -1)
+        {
+            free( closed );
+            goto failed;
+        }
+        closed->unix_fd = fd->unix_fd;
+        closed->unlink[0] = 0;
+        fd->closed = closed;
+        fd->inode = (struct inode *)grab_object( orig->inode );
+        list_add_head( &fd->inode->open, &fd->inode_entry );
+    }
+    else if ((fd->unix_fd = dup( orig->unix_fd )) == -1) goto failed;
+
+    return fd;
+
+failed:
+    release_object( fd );
+    return NULL;
+}
+
 /* set the status to return when the fd has no associated unix fd */
 void set_no_fd_status( struct fd *fd, unsigned int status )
 {
@@ -1839,6 +1892,11 @@ void fd_reselect_async( struct fd *fd, struct async_queue *queue )
     fd->fd_ops->reselect_async( fd, queue );
 }
 
+void no_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
+{
+    set_error( STATUS_OBJECT_TYPE_MISMATCH );
+}
+
 void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
 {
     struct async *async;
@@ -1927,6 +1985,13 @@ static void unmount_device( struct fd *device_fd )
     release_object( device );
 }
 
+obj_handle_t no_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async,
+                          int blocking, const void *data, data_size_t size )
+{
+    set_error( STATUS_OBJECT_TYPE_MISMATCH );
+    return 0;
+}
+
 /* default ioctl() routine */
 obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async,
                                int blocking, const void *data, data_size_t size )
diff --git a/server/file.h b/server/file.h
index 21b3879..27aed39 100644
--- a/server/file.h
+++ b/server/file.h
@@ -58,6 +58,7 @@ extern struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned i
                            unsigned int sharing, unsigned int options );
 extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops,
                                        int unix_fd, struct object *user, unsigned int options );
+extern struct fd *dup_fd_object( struct fd *orig );
 extern void *get_fd_user( struct fd *fd );
 extern void set_fd_user( struct fd *fd, const struct fd_ops *ops, struct object *user );
 extern unsigned int get_fd_options( struct fd *fd );
@@ -79,8 +80,11 @@ extern void default_poll_event( struct fd *fd, int event );
 extern struct async *fd_queue_async( struct fd *fd, const async_data_t *data, int type );
 extern void fd_async_wake_up( struct fd *fd, int type, unsigned int status );
 extern void fd_reselect_async( struct fd *fd, struct async_queue *queue );
+extern obj_handle_t no_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async,
+                                 int blocking, const void *data, data_size_t size );
 extern obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async,
                                       int blocking, const void *data, data_size_t size );
+extern void no_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
 extern void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
 extern void default_fd_reselect_async( struct fd *fd, struct async_queue *queue );
 extern void default_fd_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb );
diff --git a/server/mapping.c b/server/mapping.c
index 67760c9..e3f69a8 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -70,6 +70,7 @@ static struct object_type *mapping_get_type( struct object *obj );
 static struct fd *mapping_get_fd( struct object *obj );
 static unsigned int mapping_map_access( struct object *obj, unsigned int access );
 static void mapping_destroy( struct object *obj );
+static enum server_fd_type mapping_get_fd_type( struct fd *fd );
 
 static const struct object_ops mapping_ops =
 {
@@ -91,6 +92,18 @@ static const struct object_ops mapping_ops =
     mapping_destroy              /* destroy */
 };
 
+static const struct fd_ops mapping_fd_ops =
+{
+    default_fd_get_poll_events,   /* get_poll_events */
+    default_poll_event,           /* poll_event */
+    no_flush,                     /* flush */
+    mapping_get_fd_type,          /* get_fd_type */
+    no_fd_ioctl,                  /* ioctl */
+    no_fd_queue_async,            /* queue_async */
+    default_fd_reselect_async,    /* reselect_async */
+    default_fd_cancel_async       /* cancel_async */
+};
+
 static struct list shared_list = LIST_INIT(shared_list);
 
 #ifdef __i386__
@@ -396,6 +409,8 @@ static struct object *create_mapping( struct directory *root, const struct unico
                                       obj_handle_t handle, const struct security_descriptor *sd )
 {
     struct mapping *mapping;
+    struct file *file;
+    struct fd *fd;
     int access = 0;
     int unix_fd;
     struct stat st;
@@ -428,8 +443,14 @@ static struct object *create_mapping( struct directory *root, const struct unico
             set_error( STATUS_INVALID_PARAMETER );
             goto error;
         }
-        if (!(mapping->file = get_file_obj( current->process, handle, access ))) goto error;
-        mapping->fd = get_obj_fd( (struct object *)mapping->file );
+        if (!(file = get_file_obj( current->process, handle, access ))) goto error;
+        fd = get_obj_fd( (struct object *)file );
+        mapping->fd = dup_fd_object( fd );
+        release_object( file );
+        release_object( fd );
+        if (!mapping->fd) goto error;
+
+        set_fd_user( mapping->fd, &mapping_fd_ops, &mapping->obj );
         if ((unix_fd = get_unix_fd( mapping->fd )) == -1) goto error;
         if (protect & VPROT_IMAGE)
         {
@@ -527,6 +548,11 @@ static void mapping_destroy( struct object *obj )
     free( mapping->committed );
 }
 
+static enum server_fd_type mapping_get_fd_type( struct fd *fd )
+{
+    return FD_TYPE_FILE;
+}
+
 int get_page_size(void)
 {
     if (!page_mask) init_page_size();




More information about the wine-cvs mailing list