server: Allow specifying the status code to return on file descriptors that don't have a Unix fd.
This commit is contained in:
parent
42cd970ee0
commit
f3fbae4546
50
server/fd.c
50
server/fd.c
|
@ -170,9 +170,9 @@ struct fd
|
|||
unsigned int options; /* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */
|
||||
unsigned int sharing; /* file sharing mode */
|
||||
int unix_fd; /* unix file descriptor */
|
||||
unsigned int no_fd_status;/* status to return when unix_fd is -1 */
|
||||
int signaled :1; /* is the fd signaled? */
|
||||
int fs_locks :1; /* can we use filesystem locks for this fd? */
|
||||
int unmounted :1;/* has the device been unmounted? */
|
||||
int poll_index; /* index of fd in poll array */
|
||||
struct async_queue *read_q; /* async readers of this fd */
|
||||
struct async_queue *write_q; /* async writers of this fd */
|
||||
|
@ -1368,7 +1368,7 @@ static inline void unmount_fd( struct fd *fd )
|
|||
if (fd->unix_fd != -1) close( fd->unix_fd );
|
||||
|
||||
fd->unix_fd = -1;
|
||||
fd->unmounted = 1;
|
||||
fd->no_fd_status = STATUS_VOLUME_DISMOUNTED;
|
||||
fd->closed->unix_fd = -1;
|
||||
fd->closed->unlink[0] = 0;
|
||||
|
||||
|
@ -1393,7 +1393,6 @@ static struct fd *alloc_fd_object(void)
|
|||
fd->unix_fd = -1;
|
||||
fd->signaled = 1;
|
||||
fd->fs_locks = 1;
|
||||
fd->unmounted = 0;
|
||||
fd->poll_index = -1;
|
||||
fd->read_q = NULL;
|
||||
fd->write_q = NULL;
|
||||
|
@ -1425,16 +1424,22 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
|
|||
fd->unix_fd = -1;
|
||||
fd->signaled = 0;
|
||||
fd->fs_locks = 0;
|
||||
fd->unmounted = 0;
|
||||
fd->poll_index = -1;
|
||||
fd->read_q = NULL;
|
||||
fd->write_q = NULL;
|
||||
fd->wait_q = NULL;
|
||||
fd->no_fd_status = STATUS_BAD_DEVICE_TYPE;
|
||||
list_init( &fd->inode_entry );
|
||||
list_init( &fd->locks );
|
||||
return 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 )
|
||||
{
|
||||
fd->no_fd_status = status;
|
||||
}
|
||||
|
||||
/* check if the desired access is possible without violating */
|
||||
/* the sharing mode of other opens of the same file */
|
||||
static int check_sharing( struct fd *fd, unsigned int access, unsigned int sharing )
|
||||
|
@ -1632,11 +1637,7 @@ unsigned int get_fd_options( struct fd *fd )
|
|||
/* retrieve the unix fd for an object */
|
||||
int get_unix_fd( struct fd *fd )
|
||||
{
|
||||
if (fd->unix_fd == -1)
|
||||
{
|
||||
if (fd->unmounted) set_error( STATUS_VOLUME_DISMOUNTED );
|
||||
else set_error( STATUS_BAD_DEVICE_TYPE );
|
||||
}
|
||||
if (fd->unix_fd == -1) set_error( fd->no_fd_status );
|
||||
return fd->unix_fd;
|
||||
}
|
||||
|
||||
|
@ -1932,19 +1933,15 @@ DECL_HANDLER(get_handle_fd)
|
|||
|
||||
if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
|
||||
{
|
||||
reply->type = fd->fd_ops->get_fd_type( fd );
|
||||
if (reply->type != FD_TYPE_INVALID)
|
||||
int unix_fd = get_unix_fd( fd );
|
||||
if (unix_fd != -1)
|
||||
{
|
||||
int unix_fd = get_unix_fd( fd );
|
||||
if (unix_fd != -1)
|
||||
{
|
||||
send_client_fd( current->process, unix_fd, req->handle );
|
||||
reply->removable = is_fd_removable(fd);
|
||||
reply->options = fd->options;
|
||||
reply->access = get_handle_access( current->process, req->handle );
|
||||
}
|
||||
send_client_fd( current->process, unix_fd, req->handle );
|
||||
reply->type = fd->fd_ops->get_fd_type( fd );
|
||||
reply->removable = is_fd_removable(fd);
|
||||
reply->options = fd->options;
|
||||
reply->access = get_handle_access( current->process, req->handle );
|
||||
}
|
||||
else set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
release_object( fd );
|
||||
}
|
||||
}
|
||||
|
@ -1983,7 +1980,7 @@ DECL_HANDLER(register_async)
|
|||
|
||||
if ((fd = get_handle_fd_obj( current->process, req->handle, access )))
|
||||
{
|
||||
fd->fd_ops->queue_async( fd, &req->async, req->type, req->count );
|
||||
if (get_unix_fd( fd ) != -1) fd->fd_ops->queue_async( fd, &req->async, req->type, req->count );
|
||||
release_object( fd );
|
||||
}
|
||||
}
|
||||
|
@ -1992,15 +1989,10 @@ DECL_HANDLER(register_async)
|
|||
DECL_HANDLER(cancel_async)
|
||||
{
|
||||
struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
|
||||
|
||||
if (fd)
|
||||
{
|
||||
/* Note: we don't kill the queued APC_ASYNC_IO on this thread because
|
||||
* NtCancelIoFile() will force the pending APC to be run. Since,
|
||||
* Windows only guarantees that the current thread will have no async
|
||||
* operation on the current fd when NtCancelIoFile returns, this shall
|
||||
* do the work.
|
||||
*/
|
||||
fd->fd_ops->cancel_async( fd );
|
||||
if (get_unix_fd( fd ) != -1) fd->fd_ops->cancel_async( fd );
|
||||
release_object( fd );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ struct fd_ops
|
|||
/* file descriptor functions */
|
||||
|
||||
extern struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *user );
|
||||
extern void set_no_fd_status( struct fd *fd, unsigned int status );
|
||||
extern struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int access,
|
||||
unsigned int sharing, unsigned int options );
|
||||
extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops,
|
||||
|
|
Loading…
Reference in New Issue