Commit aa0ebd0f authored by Alexandre Julliard's avatar Alexandre Julliard

Added several file server requests

Added server-side pipes and consoles
parent 338e757d
......@@ -268,6 +268,50 @@ struct get_unix_handle_request
};
/* Get a Unix fd to read from a file */
struct get_read_fd_request
{
int handle; /* handle to the file */
};
/* Get a Unix fd to write to a file */
struct get_write_fd_request
{
int handle; /* handle to the file */
};
/* Set a file current position */
struct set_file_pointer_request
{
int handle; /* handle to the file */
int low; /* position low word */
int high; /* position high word */
int whence; /* whence to seek */
};
struct set_file_pointer_reply
{
int low; /* new position low word */
int high; /* new position high word */
};
/* Truncate (or extend) a file */
struct truncate_file_request
{
int handle; /* handle to the file */
};
/* Flush a file buffers */
struct flush_file_request
{
int handle; /* handle to the file */
};
/* Get information about a file */
struct get_file_info_request
{
int handle; /* handle to the file */
......@@ -285,6 +329,38 @@ struct get_file_info_reply
unsigned int serial; /* volume serial number */
};
/* Create an anonymous pipe */
struct create_pipe_request
{
int inherit; /* inherit flag */
};
struct create_pipe_reply
{
int handle_read; /* handle to the read-side of the pipe */
int handle_write; /* handle to the write-side of the pipe */
};
/* Create a console */
struct create_console_request
{
int inherit; /* inherit flag */
};
struct create_console_reply
{
int handle_read; /* handle to read from the console */
int handle_write; /* handle to write to the console */
};
/* Set a console file descriptor */
struct set_console_fd_request
{
int handle; /* handle to the console */
};
/* client-side functions */
#ifndef __WINE_SERVER__
......
......@@ -34,6 +34,12 @@ struct object_ops
int (*signaled)(struct object *,struct thread *);
/* wait satisfied; return 1 if abandoned */
int (*satisfied)(struct object *,struct thread *);
/* return a Unix fd that can be used to read from the object */
int (*get_read_fd)(struct object *);
/* return a Unix fd that can be used to write to the object */
int (*get_write_fd)(struct object *);
/* flush the object buffers */
int (*flush)(struct object *);
/* destroy on refcount == 0 */
void (*destroy)(struct object *);
};
......@@ -57,6 +63,11 @@ extern int init_object( struct object *obj, const struct object_ops *ops,
extern struct object *grab_object( void *obj );
extern void release_object( void *obj );
extern struct object *find_object( const char *name );
extern int no_satisfied( struct object *obj, struct thread *thread );
extern int no_read_fd( struct object *obj );
extern int no_write_fd( struct object *obj );
extern int no_flush( struct object *obj );
extern void default_select_event( int fd, int event, void *private );
/* request handlers */
......@@ -161,7 +172,22 @@ extern int release_semaphore( int handle, unsigned int count, unsigned int *prev
extern struct object *create_file( int fd );
extern int file_get_unix_handle( int handle, unsigned int access );
extern int set_file_pointer( int handle, int *low, int *high, int whence );
extern int truncate_file( int handle );
extern int get_file_info( int handle, struct get_file_info_reply *reply );
extern void file_set_error(void);
/* pipe functions */
extern int create_pipe( struct object *obj[2] );
/* console functions */
extern int create_console( int fd, struct object *obj[2] );
extern int set_console_fd( int handle, int fd );
extern int debug_level;
......
......@@ -25,7 +25,15 @@ enum request
REQ_OPEN_NAMED_OBJ,
REQ_CREATE_FILE,
REQ_GET_UNIX_HANDLE,
REQ_GET_READ_FD,
REQ_GET_WRITE_FD,
REQ_SET_FILE_POINTER,
REQ_TRUNCATE_FILE,
REQ_FLUSH_FILE,
REQ_GET_FILE_INFO,
REQ_CREATE_PIPE,
REQ_CREATE_CONSOLE,
REQ_SET_CONSOLE_FD,
REQ_NB_REQUESTS
};
......@@ -54,7 +62,15 @@ DECL_HANDLER(release_semaphore);
DECL_HANDLER(open_named_obj);
DECL_HANDLER(create_file);
DECL_HANDLER(get_unix_handle);
DECL_HANDLER(get_read_fd);
DECL_HANDLER(get_write_fd);
DECL_HANDLER(set_file_pointer);
DECL_HANDLER(truncate_file);
DECL_HANDLER(flush_file);
DECL_HANDLER(get_file_info);
DECL_HANDLER(create_pipe);
DECL_HANDLER(create_console);
DECL_HANDLER(set_console_fd);
static const struct handler {
void (*handler)();
......@@ -80,7 +96,15 @@ static const struct handler {
{ (void(*)())req_open_named_obj, sizeof(struct open_named_obj_request) },
{ (void(*)())req_create_file, sizeof(struct create_file_request) },
{ (void(*)())req_get_unix_handle, sizeof(struct get_unix_handle_request) },
{ (void(*)())req_get_read_fd, sizeof(struct get_read_fd_request) },
{ (void(*)())req_get_write_fd, sizeof(struct get_write_fd_request) },
{ (void(*)())req_set_file_pointer, sizeof(struct set_file_pointer_request) },
{ (void(*)())req_truncate_file, sizeof(struct truncate_file_request) },
{ (void(*)())req_flush_file, sizeof(struct flush_file_request) },
{ (void(*)())req_get_file_info, sizeof(struct get_file_info_request) },
{ (void(*)())req_create_pipe, sizeof(struct create_pipe_request) },
{ (void(*)())req_create_console, sizeof(struct create_console_request) },
{ (void(*)())req_set_console_fd, sizeof(struct set_console_fd_request) },
};
#endif /* WANT_REQUEST_HANDLERS */
......
......@@ -6,10 +6,12 @@ VPATH = @srcdir@
MODULE = server
C_SRCS = \
console.c \
event.c \
file.c \
mutex.c \
object.c \
pipe.c \
process.c \
request.c \
select.c \
......
/*
* Server-side console management
*
* Copyright (C) 1998 Alexandre Julliard
*
* FIXME: all this stuff is a hack to avoid breaking
* the client-side console support.
*/
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "winerror.h"
#include "winnt.h"
#include "server/thread.h"
struct console
{
struct object obj; /* object header */
int fd; /* Unix file descriptor */
int is_read; /* is this the read or write part? */
};
static void console_dump( struct object *obj, int verbose );
static void console_add_queue( struct object *obj, struct wait_queue_entry *entry );
static void console_remove_queue( struct object *obj, struct wait_queue_entry *entry );
static int console_signaled( struct object *obj, struct thread *thread );
static int console_get_read_fd( struct object *obj );
static int console_get_write_fd( struct object *obj );
static void console_destroy( struct object *obj );
static const struct object_ops console_ops =
{
console_dump,
console_add_queue,
console_remove_queue,
console_signaled,
no_satisfied,
console_get_read_fd,
console_get_write_fd,
no_flush,
console_destroy
};
static const struct select_ops select_ops =
{
default_select_event,
NULL /* we never set a timeout on a console */
};
int create_console( int fd, struct object *obj[2] )
{
struct console *console_read, *console_write;
int read_fd, write_fd;
if ((read_fd = (fd != -1) ? dup(fd) : dup(0)) == -1)
{
file_set_error();
return 0;
}
if ((write_fd = (fd != -1) ? dup(fd) : dup(0)) == -1)
{
file_set_error();
close( read_fd );
return 0;
}
if (!(console_read = mem_alloc( sizeof(struct console) )))
{
close( read_fd );
close( write_fd );
return 0;
}
if (!(console_write = mem_alloc( sizeof(struct console) )))
{
close( read_fd );
close( write_fd );
free( console_read );
return 0;
}
init_object( &console_read->obj, &console_ops, NULL );
init_object( &console_write->obj, &console_ops, NULL );
console_read->fd = read_fd;
console_read->is_read = 1;
console_write->fd = write_fd;
console_write->is_read = 0;
CLEAR_ERROR();
obj[0] = &console_read->obj;
obj[1] = &console_write->obj;
return 1;
}
int set_console_fd( int handle, int fd )
{
struct console *console;
if (!(console = (struct console *)get_handle_obj( current->process, handle,
0, &console_ops )))
return 0;
if ((fd = dup(fd)) == -1)
{
file_set_error();
release_object( console );
return 0;
}
close( console->fd );
console->fd = fd;
release_object( console );
return 1;
}
static void console_dump( struct object *obj, int verbose )
{
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
printf( "Console %s fd=%d\n",
console->is_read ? "input" : "output", console->fd );
}
static void console_add_queue( struct object *obj, struct wait_queue_entry *entry )
{
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
if (!obj->head) /* first on the queue */
add_select_user( console->fd,
console->is_read ? READ_EVENT : WRITE_EVENT,
&select_ops, console );
add_queue( obj, entry );
}
static void console_remove_queue( struct object *obj, struct wait_queue_entry *entry )
{
struct console *console = (struct console *)grab_object(obj);
assert( obj->ops == &console_ops );
remove_queue( obj, entry );
if (!obj->head) /* last on the queue is gone */
remove_select_user( console->fd );
release_object( obj );
}
static int console_signaled( struct object *obj, struct thread *thread )
{
fd_set fds;
struct timeval tv = { 0, 0 };
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
FD_ZERO( &fds );
FD_SET( console->fd, &fds );
if (console->is_read)
return select( console->fd + 1, &fds, NULL, NULL, &tv ) > 0;
else
return select( console->fd + 1, NULL, &fds, NULL, &tv ) > 0;
}
static int console_get_read_fd( struct object *obj )
{
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
if (!console->is_read)
{
SET_ERROR( ERROR_ACCESS_DENIED );
return -1;
}
return dup( console->fd );
}
static int console_get_write_fd( struct object *obj )
{
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
if (console->is_read)
{
SET_ERROR( ERROR_ACCESS_DENIED );
return -1;
}
return dup( console->fd );
}
static void console_destroy( struct object *obj )
{
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
close( console->fd );
free( console );
}
......@@ -31,6 +31,9 @@ static const struct object_ops event_ops =
remove_queue,
event_signaled,
event_satisfied,
no_read_fd,
no_write_fd,
no_flush,
event_destroy
};
......
......@@ -30,7 +30,9 @@ static void file_dump( struct object *obj, int verbose );
static void file_add_queue( struct object *obj, struct wait_queue_entry *entry );
static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry );
static int file_signaled( struct object *obj, struct thread *thread );
static int file_satisfied( struct object *obj, struct thread *thread );
static int file_get_read_fd( struct object *obj );
static int file_get_write_fd( struct object *obj );
static int file_flush( struct object *obj );
static void file_destroy( struct object *obj );
static const struct object_ops file_ops =
......@@ -39,17 +41,17 @@ static const struct object_ops file_ops =
file_add_queue,
file_remove_queue,
file_signaled,
file_satisfied,
no_satisfied,
file_get_read_fd,
file_get_write_fd,
file_flush,
file_destroy
};
static void file_event( int fd, int event, void *private );
static void file_timeout( int fd, void *private );
static const struct select_ops select_ops =
{
file_event,
file_timeout
default_select_event,
NULL /* we never set a timeout on a file */
};
struct object *create_file( int fd )
......@@ -123,32 +125,74 @@ static int file_signaled( struct object *obj, struct thread *thread )
return select( file->fd + 1, &read_fds, &write_fds, NULL, &tv ) > 0;
}
static int file_satisfied( struct object *obj, struct thread *thread )
static int file_get_read_fd( struct object *obj )
{
/* Nothing to do */
return 0; /* Not abandoned */
struct file *file = (struct file *)obj;
assert( obj->ops == &file_ops );
if (!(file->event & READ_EVENT)) /* FIXME: should not be necessary */
{
SET_ERROR( ERROR_ACCESS_DENIED );
return -1;
}
return dup( file->fd );
}
static void file_destroy( struct object *obj )
static int file_get_write_fd( struct object *obj )
{
struct file *file = (struct file *)obj;
assert( obj->ops == &file_ops );
close( file->fd );
free( file );
if (!(file->event & WRITE_EVENT)) /* FIXME: should not be necessary */
{
SET_ERROR( ERROR_ACCESS_DENIED );
return -1;
}
return dup( file->fd );
}
static void file_event( int fd, int event, void *private )
static int file_flush( struct object *obj )
{
struct file *file = (struct file *)private;
assert( file );
int ret;
struct file *file = (struct file *)grab_object(obj);
assert( obj->ops == &file_ops );
wake_up( &file->obj, 0 );
ret = (fsync( file->fd ) != -1);
if (!ret) file_set_error();
release_object( file );
return ret;
}
static void file_timeout( int fd, void *private )
static void file_destroy( struct object *obj )
{
/* we never set a timeout on a file */
assert( 0 );
struct file *file = (struct file *)obj;
assert( obj->ops == &file_ops );
close( file->fd );
free( file );
}
/* set the last error depending on errno */
void file_set_error(void)
{
switch (errno)
{
case EAGAIN: SET_ERROR( ERROR_SHARING_VIOLATION ); break;
case EBADF: SET_ERROR( ERROR_INVALID_HANDLE ); break;
case ENOSPC: SET_ERROR( ERROR_HANDLE_DISK_FULL ); break;
case EACCES:
case EPERM: SET_ERROR( ERROR_ACCESS_DENIED ); break;
case EROFS: SET_ERROR( ERROR_WRITE_PROTECT ); break;
case EBUSY: SET_ERROR( ERROR_LOCK_VIOLATION ); break;
case ENOENT: SET_ERROR( ERROR_FILE_NOT_FOUND ); break;
case EISDIR: SET_ERROR( ERROR_CANNOT_MAKE ); break;
case ENFILE:
case EMFILE: SET_ERROR( ERROR_NO_MORE_FILES ); break;
case EEXIST: SET_ERROR( ERROR_FILE_EXISTS ); break;
case EINVAL: SET_ERROR( ERROR_INVALID_PARAMETER ); break;
case ESPIPE: SET_ERROR( ERROR_SEEK ); break;
case ENOTEMPTY: SET_ERROR( ERROR_DIR_NOT_EMPTY ); break;
default: perror("file_set_error"); SET_ERROR( ERROR_UNKNOWN ); break;
}
}
int file_get_unix_handle( int handle, unsigned int access )
......@@ -164,6 +208,56 @@ int file_get_unix_handle( int handle, unsigned int access )
return unix_handle;
}
int set_file_pointer( int handle, int *low, int *high, int whence )
{
struct file *file;
int result;
if (*high)
{
fprintf( stderr, "set_file_pointer: offset > 4Gb not supported yet\n" );
SET_ERROR( ERROR_INVALID_PARAMETER );
return 0;
}
if (!(file = (struct file *)get_handle_obj( current->process, handle,
0, &file_ops )))
return 0;
if ((result = lseek( file->fd, *low, whence )) == -1)
{
/* Check for seek before start of file */
if ((errno == EINVAL) && (whence != SEEK_SET) && (*low < 0))
SET_ERROR( ERROR_NEGATIVE_SEEK );
else
file_set_error();
release_object( file );
return 0;
}
*low = result;
release_object( file );
return 1;
}
int truncate_file( int handle )
{
struct file *file;
int result;
if (!(file = (struct file *)get_handle_obj( current->process, handle,
GENERIC_WRITE, &file_ops )))
return 0;
if (((result = lseek( file->fd, 0, SEEK_CUR )) == -1) ||
(ftruncate( file->fd, result ) == -1))
{
file_set_error();
release_object( file );
return 0;
}
release_object( file );
return 1;
}
int get_file_info( int handle, struct get_file_info_reply *reply )
{
struct file *file;
......@@ -174,7 +268,7 @@ int get_file_info( int handle, struct get_file_info_reply *reply )
return 0;
if (fstat( file->fd, &st ) == -1)
{
/* file_set_error(); */
file_set_error();
release_object( file );
return 0;
}
......
......@@ -34,6 +34,9 @@ static const struct object_ops mutex_ops =
remove_queue,
mutex_signaled,
mutex_satisfied,
no_read_fd,
no_write_fd,
no_flush,
mutex_destroy
};
......
......@@ -144,3 +144,35 @@ struct object *find_object( const char *name )
if (!ptr) return NULL;
return grab_object( ptr->obj );
}
/* functions for unimplemented object operations */
int no_satisfied( struct object *obj, struct thread *thread )
{
return 0; /* not abandoned */
}
int no_read_fd( struct object *obj )
{
SET_ERROR( ERROR_INVALID_HANDLE );
return -1;
}
int no_write_fd( struct object *obj )
{
SET_ERROR( ERROR_INVALID_HANDLE );
return -1;
}
int no_flush( struct object *obj )
{
SET_ERROR( ERROR_INVALID_HANDLE );
return 0;
}
void default_select_event( int fd, int event, void *private )
{
struct object *obj = (struct object *)private;
assert( obj );
wake_up( obj, 0 );
}
/*
* Server-side pipe management
*
* Copyright (C) 1998 Alexandre Julliard
*/
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "winerror.h"
#include "winnt.h"
#include "server/thread.h"
enum side { READ_SIDE, WRITE_SIDE };
struct pipe
{
struct object obj; /* object header */
struct pipe *other; /* the pipe other end */
int fd; /* Unix file descriptor */
enum side side; /* which side of the pipe is this */
};
static void pipe_dump( struct object *obj, int verbose );
static void pipe_add_queue( struct object *obj, struct wait_queue_entry *entry );
static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entry );
static int pipe_signaled( struct object *obj, struct thread *thread );
static int pipe_get_read_fd( struct object *obj );
static int pipe_get_write_fd( struct object *obj );
static void pipe_destroy( struct object *obj );
static const struct object_ops pipe_ops =
{
pipe_dump,
pipe_add_queue,
pipe_remove_queue,
pipe_signaled,
no_satisfied,
pipe_get_read_fd,
pipe_get_write_fd,
no_flush,
pipe_destroy
};
static const struct select_ops select_ops =
{
default_select_event,
NULL /* we never set a timeout on a pipe */
};
int create_pipe( struct object *obj[2] )
{
struct pipe *newpipe[2];
int fd[2];
if (pipe( fd ) == -1)
{
file_set_error();
return 0;
}
if (!(newpipe[0] = mem_alloc( sizeof(struct pipe) )))
{
close( fd[0] );
close( fd[1] );
return 0;
}
if (!(newpipe[1] = mem_alloc( sizeof(struct pipe) )))
{
close( fd[0] );
close( fd[1] );
free( newpipe[0] );
return 0;
}
init_object( &newpipe[0]->obj, &pipe_ops, NULL );
init_object( &newpipe[1]->obj, &pipe_ops, NULL );
newpipe[0]->fd = fd[0];
newpipe[0]->other = newpipe[1];
newpipe[0]->side = READ_SIDE;
newpipe[1]->fd = fd[1];
newpipe[1]->other = newpipe[0];
newpipe[1]->side = WRITE_SIDE;
obj[0] = &newpipe[0]->obj;
obj[1] = &newpipe[1]->obj;
CLEAR_ERROR();
return 1;
}
static void pipe_dump( struct object *obj, int verbose )
{
struct pipe *pipe = (struct pipe *)obj;
assert( obj->ops == &pipe_ops );
printf( "Pipe %s-side fd=%d\n",
(pipe->side == READ_SIDE) ? "read" : "write", pipe->fd );
}
static void pipe_add_queue( struct object *obj, struct wait_queue_entry *entry )
{
struct pipe *pipe = (struct pipe *)obj;
assert( obj->ops == &pipe_ops );
if (!obj->head) /* first on the queue */
add_select_user( pipe->fd,
(pipe->side == READ_SIDE) ? READ_EVENT : WRITE_EVENT,
&select_ops, pipe );
add_queue( obj, entry );
}
static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entry )
{
struct pipe *pipe = (struct pipe *)grab_object(obj);
assert( obj->ops == &pipe_ops );
remove_queue( obj, entry );
if (!obj->head) /* last on the queue is gone */
remove_select_user( pipe->fd );
release_object( obj );
}
static int pipe_signaled( struct object *obj, struct thread *thread )
{
struct pipe *pipe = (struct pipe *)obj;
struct timeval tv = { 0, 0 };
fd_set fds;
assert( obj->ops == &pipe_ops );
FD_ZERO( &fds );
FD_SET( pipe->fd, &fds );
if (pipe->side == READ_SIDE)
return select( pipe->fd + 1, &fds, NULL, NULL, &tv ) > 0;
else
return select( pipe->fd + 1, NULL, &fds, NULL, &tv ) > 0;
}
static int pipe_get_read_fd( struct object *obj )
{
struct pipe *pipe = (struct pipe *)obj;
assert( obj->ops == &pipe_ops );
if (!pipe->other)
{
SET_ERROR( ERROR_BROKEN_PIPE );
return -1;
}
if (pipe->side != READ_SIDE) /* FIXME: should not be necessary */
{
SET_ERROR( ERROR_ACCESS_DENIED );
return -1;
}
return dup( pipe->fd );
}
static int pipe_get_write_fd( struct object *obj )
{
struct pipe *pipe = (struct pipe *)obj;
assert( obj->ops == &pipe_ops );
if (!pipe->other)
{
SET_ERROR( ERROR_BROKEN_PIPE );
return -1;
}
if (pipe->side != WRITE_SIDE) /* FIXME: should not be necessary */
{
SET_ERROR( ERROR_ACCESS_DENIED );
return -1;
}
return dup( pipe->fd );
}
static void pipe_destroy( struct object *obj )
{
struct pipe *pipe = (struct pipe *)obj;
assert( obj->ops == &pipe_ops );
if (pipe->other) pipe->other->other = NULL;
close( pipe->fd );
free( pipe );
}
......@@ -56,7 +56,6 @@ static struct process *first_process;
static void process_dump( struct object *obj, int verbose );
static int process_signaled( struct object *obj, struct thread *thread );
static int process_satisfied( struct object *obj, struct thread *thread );
static void process_destroy( struct object *obj );
static void free_handles( struct process *process );
static int copy_handle_table( struct process *process, struct process *parent );
......@@ -67,7 +66,10 @@ static const struct object_ops process_ops =
add_queue,
remove_queue,
process_signaled,
process_satisfied,
no_satisfied,
no_read_fd,
no_write_fd,
no_flush,
process_destroy
};
......@@ -130,11 +132,6 @@ static int process_signaled( struct object *obj, struct thread *thread )
return (process->running_threads > 0);
}
static int process_satisfied( struct object *obj, struct thread *thread )
{
return 0;
}
/* get a process from an id (and increment the refcount) */
struct process *get_process_from_id( void *id )
{
......
......@@ -4,6 +4,7 @@
* Copyright (C) 1998 Alexandre Julliard
*/
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -156,6 +157,8 @@ DECL_HANDLER(init_thread)
DECL_HANDLER(set_debug)
{
debug_level = req->level;
/* Make sure last_req is initialized */
current->last_req = REQ_SET_DEBUG;
CLEAR_ERROR();
send_reply( current, -1, 0 );
}
......@@ -408,6 +411,64 @@ DECL_HANDLER(get_unix_handle)
send_reply( current, handle, 0 );
}
/* get a Unix fd to read from a file */
DECL_HANDLER(get_read_fd)
{
struct object *obj;
int read_fd;
if ((obj = get_handle_obj( current->process, req->handle, GENERIC_READ, NULL )))
{
read_fd = obj->ops->get_read_fd( obj );
release_object( obj );
}
else read_fd = -1;
send_reply( current, read_fd, 0 );
}
/* get a Unix fd to write to a file */
DECL_HANDLER(get_write_fd)
{
struct object *obj;
int write_fd;
if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL )))
{
write_fd = obj->ops->get_write_fd( obj );
release_object( obj );
}
else write_fd = -1;
send_reply( current, write_fd, 0 );
}
/* set a file current position */
DECL_HANDLER(set_file_pointer)
{
struct set_file_pointer_reply reply = { req->low, req->high };
set_file_pointer( req->handle, &reply.low, &reply.high, req->whence );
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* truncate (or extend) a file */
DECL_HANDLER(truncate_file)
{
truncate_file( req->handle );
send_reply( current, -1, 0 );
}
/* flush a file buffers */
DECL_HANDLER(flush_file)
{
struct object *obj;
if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL )))
{
obj->ops->flush( obj );
release_object( obj );
}
send_reply( current, -1, 0 );
}
/* get a file information */
DECL_HANDLER(get_file_info)
{
......@@ -415,3 +476,58 @@ DECL_HANDLER(get_file_info)
get_file_info( req->handle, &reply );
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* create an anonymous pipe */
DECL_HANDLER(create_pipe)
{
struct create_pipe_reply reply = { -1, -1 };
struct object *obj[2];
if (create_pipe( obj ))
{
reply.handle_read = alloc_handle( current->process, obj[0],
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
req->inherit );
if (reply.handle_read != -1)
{
reply.handle_write = alloc_handle( current->process, obj[1],
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
req->inherit );
if (reply.handle_write == -1)
close_handle( current->process, reply.handle_read );
}
release_object( obj[0] );
release_object( obj[1] );
}
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* create a console */
DECL_HANDLER(create_console)
{
struct create_console_reply reply = { -1, -1 };
struct object *obj[2];
if (create_console( fd, obj ))
{
reply.handle_read = alloc_handle( current->process, obj[0],
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
req->inherit );
if (reply.handle_read != -1)
{
reply.handle_write = alloc_handle( current->process, obj[1],
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
req->inherit );
if (reply.handle_write == -1)
close_handle( current->process, reply.handle_read );
}
release_object( obj[0] );
release_object( obj[1] );
}
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* set a console fd */
DECL_HANDLER(set_console_fd)
{
set_console_fd( req->handle, fd );
send_reply( current, -1, 0 );
}
......@@ -31,6 +31,9 @@ static const struct object_ops semaphore_ops =
remove_queue,
semaphore_signaled,
semaphore_satisfied,
no_read_fd,
no_write_fd,
no_flush,
semaphore_destroy
};
......
......@@ -43,7 +43,6 @@ struct thread_wait
static void dump_thread( struct object *obj, int verbose );
static int thread_signaled( struct object *obj, struct thread *thread );
static int thread_satisfied( struct object *obj, struct thread *thread );
static void destroy_thread( struct object *obj );
static const struct object_ops thread_ops =
......@@ -52,7 +51,10 @@ static const struct object_ops thread_ops =
add_queue,
remove_queue,
thread_signaled,
thread_satisfied,
no_satisfied,
no_read_fd,
no_write_fd,
no_flush,
destroy_thread
};
......@@ -153,11 +155,6 @@ static int thread_signaled( struct object *obj, struct thread *thread )
return (mythread->state == TERMINATED);
}
static int thread_satisfied( struct object *obj, struct thread *thread )
{
return 0;
}
/* get a thread pointer from a thread id (and increment the refcount) */
struct thread *get_thread_from_id( void *id )
{
......
......@@ -229,6 +229,46 @@ static int dump_get_unix_handle_request( struct get_unix_handle_request *req, in
return (int)sizeof(*req);
}
static int dump_get_read_fd_request( struct get_read_fd_request *req, int len )
{
printf( " handle=%d", req->handle );
return (int)sizeof(*req);
}
static int dump_get_write_fd_request( struct get_write_fd_request *req, int len )
{
printf( " handle=%d", req->handle );
return (int)sizeof(*req);
}
static int dump_set_file_pointer_request( struct set_file_pointer_request *req, int len )
{
printf( " handle=%d,", req->handle );
printf( " low=%d,", req->low );
printf( " high=%d,", req->high );
printf( " whence=%d", req->whence );
return (int)sizeof(*req);
}
static int dump_set_file_pointer_reply( struct set_file_pointer_reply *req, int len )
{
printf( " low=%d,", req->low );
printf( " high=%d", req->high );
return (int)sizeof(*req);
}
static int dump_truncate_file_request( struct truncate_file_request *req, int len )
{
printf( " handle=%d", req->handle );
return (int)sizeof(*req);
}
static int dump_flush_file_request( struct flush_file_request *req, int len )
{
printf( " handle=%d", req->handle );
return (int)sizeof(*req);
}
static int dump_get_file_info_request( struct get_file_info_request *req, int len )
{
printf( " handle=%d", req->handle );
......@@ -249,6 +289,38 @@ static int dump_get_file_info_reply( struct get_file_info_reply *req, int len )
return (int)sizeof(*req);
}
static int dump_create_pipe_request( struct create_pipe_request *req, int len )
{
printf( " inherit=%d", req->inherit );
return (int)sizeof(*req);
}
static int dump_create_pipe_reply( struct create_pipe_reply *req, int len )
{
printf( " handle_read=%d,", req->handle_read );
printf( " handle_write=%d", req->handle_write );
return (int)sizeof(*req);
}
static int dump_create_console_request( struct create_console_request *req, int len )
{
printf( " inherit=%d", req->inherit );
return (int)sizeof(*req);
}
static int dump_create_console_reply( struct create_console_reply *req, int len )
{
printf( " handle_read=%d,", req->handle_read );
printf( " handle_write=%d", req->handle_write );
return (int)sizeof(*req);
}
static int dump_set_console_fd_request( struct set_console_fd_request *req, int len )
{
printf( " handle=%d", req->handle );
return (int)sizeof(*req);
}
struct dumper
{
int (*dump_req)( void *data, int len );
......@@ -297,8 +369,24 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] =
(void(*)())dump_create_file_reply },
{ (int(*)(void *,int))dump_get_unix_handle_request,
(void(*)())0 },
{ (int(*)(void *,int))dump_get_read_fd_request,
(void(*)())0 },
{ (int(*)(void *,int))dump_get_write_fd_request,
(void(*)())0 },
{ (int(*)(void *,int))dump_set_file_pointer_request,
(void(*)())dump_set_file_pointer_reply },
{ (int(*)(void *,int))dump_truncate_file_request,
(void(*)())0 },
{ (int(*)(void *,int))dump_flush_file_request,
(void(*)())0 },
{ (int(*)(void *,int))dump_get_file_info_request,
(void(*)())dump_get_file_info_reply },
{ (int(*)(void *,int))dump_create_pipe_request,
(void(*)())dump_create_pipe_reply },
{ (int(*)(void *,int))dump_create_console_request,
(void(*)())dump_create_console_reply },
{ (int(*)(void *,int))dump_set_console_fd_request,
(void(*)())0 },
};
static const char * const req_names[REQ_NB_REQUESTS] =
......@@ -323,7 +411,15 @@ static const char * const req_names[REQ_NB_REQUESTS] =
"open_named_obj",
"create_file",
"get_unix_handle",
"get_read_fd",
"get_write_fd",
"set_file_pointer",
"truncate_file",
"flush_file",
"get_file_info",
"create_pipe",
"create_console",
"set_console_fd",
};
void trace_request( enum request req, void *data, int len, int fd )
......
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