server: Store a duplicate of the file descriptor for file mappings.
This commit is contained in:
parent
0f4068ac6f
commit
5f808f03e1
65
server/fd.c
65
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 )
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue