Commit 5f808f03 authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent 0f4068ac
...@@ -1488,6 +1488,59 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use ...@@ -1488,6 +1488,59 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
return fd; 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 */ /* set the status to return when the fd has no associated unix fd */
void set_no_fd_status( struct fd *fd, unsigned int status ) 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 ) ...@@ -1839,6 +1892,11 @@ void fd_reselect_async( struct fd *fd, struct async_queue *queue )
fd->fd_ops->reselect_async( fd, 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 ) void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
{ {
struct async *async; struct async *async;
...@@ -1927,6 +1985,13 @@ static void unmount_device( struct fd *device_fd ) ...@@ -1927,6 +1985,13 @@ static void unmount_device( struct fd *device_fd )
release_object( device ); 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 */ /* default ioctl() routine */
obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async, 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 ) int blocking, const void *data, data_size_t size )
......
...@@ -58,6 +58,7 @@ extern struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned i ...@@ -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 ); unsigned int sharing, unsigned int options );
extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops,
int unix_fd, struct object *user, unsigned int options ); 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 *get_fd_user( struct fd *fd );
extern void set_fd_user( struct fd *fd, const struct fd_ops *ops, struct object *user ); 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 ); extern unsigned int get_fd_options( struct fd *fd );
...@@ -79,8 +80,11 @@ extern void default_poll_event( struct fd *fd, int event ); ...@@ -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 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_async_wake_up( struct fd *fd, int type, unsigned int status );
extern void fd_reselect_async( struct fd *fd, struct async_queue *queue ); 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, 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 ); 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_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_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 ); extern void default_fd_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb );
......
...@@ -70,6 +70,7 @@ static struct object_type *mapping_get_type( struct object *obj ); ...@@ -70,6 +70,7 @@ static struct object_type *mapping_get_type( struct object *obj );
static struct fd *mapping_get_fd( 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 unsigned int mapping_map_access( struct object *obj, unsigned int access );
static void mapping_destroy( struct object *obj ); 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 = static const struct object_ops mapping_ops =
{ {
...@@ -91,6 +92,18 @@ static const struct object_ops mapping_ops = ...@@ -91,6 +92,18 @@ static const struct object_ops mapping_ops =
mapping_destroy /* destroy */ 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); static struct list shared_list = LIST_INIT(shared_list);
#ifdef __i386__ #ifdef __i386__
...@@ -396,6 +409,8 @@ static struct object *create_mapping( struct directory *root, const struct unico ...@@ -396,6 +409,8 @@ static struct object *create_mapping( struct directory *root, const struct unico
obj_handle_t handle, const struct security_descriptor *sd ) obj_handle_t handle, const struct security_descriptor *sd )
{ {
struct mapping *mapping; struct mapping *mapping;
struct file *file;
struct fd *fd;
int access = 0; int access = 0;
int unix_fd; int unix_fd;
struct stat st; struct stat st;
...@@ -428,8 +443,14 @@ static struct object *create_mapping( struct directory *root, const struct unico ...@@ -428,8 +443,14 @@ static struct object *create_mapping( struct directory *root, const struct unico
set_error( STATUS_INVALID_PARAMETER ); set_error( STATUS_INVALID_PARAMETER );
goto error; goto error;
} }
if (!(mapping->file = get_file_obj( current->process, handle, access ))) goto error; if (!(file = get_file_obj( current->process, handle, access ))) goto error;
mapping->fd = get_obj_fd( (struct object *)mapping->file ); 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 ((unix_fd = get_unix_fd( mapping->fd )) == -1) goto error;
if (protect & VPROT_IMAGE) if (protect & VPROT_IMAGE)
{ {
...@@ -527,6 +548,11 @@ static void mapping_destroy( struct object *obj ) ...@@ -527,6 +548,11 @@ static void mapping_destroy( struct object *obj )
free( mapping->committed ); free( mapping->committed );
} }
static enum server_fd_type mapping_get_fd_type( struct fd *fd )
{
return FD_TYPE_FILE;
}
int get_page_size(void) int get_page_size(void)
{ {
if (!page_mask) init_page_size(); if (!page_mask) init_page_size();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment