Module: wine Branch: master Commit: 5f808f03e1bc379fb02eaf4b16a43247410c7003 URL: http://source.winehq.org/git/wine.git/?a=commit;h=5f808f03e1bc379fb02eaf4b16...
Author: Alexandre Julliard julliard@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();