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

This commit is contained in:
Alexandre Julliard 2009-11-23 16:16:46 +01:00
parent 0f4068ac6f
commit 5f808f03e1
3 changed files with 97 additions and 2 deletions

View File

@ -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 )

View File

@ -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 );

View File

@ -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();