From 863637b158114511bb14e01ca555c580f0ef20b1 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard <julliard@winehq.org> Date: Thu, 30 Jan 2003 00:26:44 +0000 Subject: [PATCH] Started moving functions that deal with Unix file descriptors to a separate fd object. This will be needed for file locking. --- server/Makefile.in | 1 + server/async.c | 31 ------ server/atom.c | 4 - server/change.c | 4 - server/console.c | 12 --- server/debugger.c | 8 -- server/device.c | 4 - server/event.c | 4 - server/fd.c | 244 ++++++++++++++++++++++++++++++++++++++++++++ server/file.c | 86 +++++++--------- server/file.h | 56 ++++++++++ server/handle.c | 4 - server/hook.c | 4 - server/mapping.c | 20 ++-- server/mutex.c | 4 - server/named_pipe.c | 33 +++--- server/object.c | 47 ++------- server/object.h | 20 +--- server/pipe.c | 28 +++-- server/process.c | 18 ++-- server/queue.c | 8 -- server/registry.c | 10 +- server/request.c | 14 ++- server/select.c | 4 +- server/semaphore.c | 4 - server/serial.c | 39 +++---- server/smb.c | 28 +++-- server/snapshot.c | 4 - server/sock.c | 33 +++--- server/thread.c | 14 ++- server/timer.c | 4 - 31 files changed, 465 insertions(+), 329 deletions(-) create mode 100644 server/fd.c create mode 100644 server/file.h diff --git a/server/Makefile.in b/server/Makefile.in index 543b8e36509..bfdc29b9012 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -16,6 +16,7 @@ C_SRCS = \ debugger.c \ device.c \ event.c \ + fd.c \ file.c \ handle.c \ hook.c \ diff --git a/server/async.c b/server/async.c index 5bbbb44aa1a..2249fa1f889 100644 --- a/server/async.c +++ b/server/async.c @@ -147,34 +147,3 @@ void async_add_timeout(struct async *async, int timeout) async->timeout = add_timeout_user( &async->when, async_callback, async ); } } - -DECL_HANDLER(register_async) -{ - struct object *obj = get_handle_obj( current->process, req->handle, 0, NULL); - - if ( !(obj) || !obj->ops->queue_async ) - { - set_error(STATUS_INVALID_HANDLE); - return; - } - -/* - * The queue_async method must do the following: - * - * 1. Get the async_queue for the request of given type. - * 2. Call find_async() to look for the specific client request in the queue (=> NULL if not found). - * 3. If status is STATUS_PENDING: - * a) If no async request found in step 2 (new request): call create_async() to initialize one. - * b) Set request's status to STATUS_PENDING. - * c) If the "queue" field of the async request is NULL: call async_insert() to put it into the queue. - * Otherwise: - * If the async request was found in step 2, destroy it by calling destroy_async(). - * 4. Carry out any operations necessary to adjust the object's poll events - * Usually: set_elect_events (obj, obj->ops->get_poll_events()). - * - * See also the implementations in file.c, serial.c, and sock.c. -*/ - - obj->ops->queue_async (obj, req->overlapped, req->status, req->type, req->count); - release_object(obj); -} diff --git a/server/atom.c b/server/atom.c index 3ab80861f90..40b07f4cf94 100644 --- a/server/atom.c +++ b/server/atom.c @@ -71,12 +71,8 @@ static const struct object_ops atom_table_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satified */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ atom_table_destroy /* destroy */ }; diff --git a/server/change.c b/server/change.c index a6316426472..e110eadfeeb 100644 --- a/server/change.c +++ b/server/change.c @@ -46,12 +46,8 @@ static const struct object_ops change_ops = remove_queue, /* remove_queue */ change_signaled, /* signaled */ no_satisfied, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ no_destroy /* destroy */ }; diff --git a/server/console.c b/server/console.c index e7e4f317018..6288a1a02eb 100644 --- a/server/console.c +++ b/server/console.c @@ -51,12 +51,8 @@ static const struct object_ops console_input_ops = remove_queue, /* remove_queue */ console_input_signaled, /* signaled */ no_satisfied, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ console_get_file_info, /* get_file_info */ - NULL, /* queue_async */ console_input_destroy /* destroy */ }; @@ -80,12 +76,8 @@ static const struct object_ops console_input_events_ops = remove_queue, /* remove_queue */ console_input_events_signaled, /* signaled */ no_satisfied, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ console_input_events_destroy /* destroy */ }; @@ -121,12 +113,8 @@ static const struct object_ops screen_buffer_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ console_get_file_info, /* get_file_info */ - NULL, /* queue_async */ screen_buffer_destroy /* destroy */ }; diff --git a/server/debugger.c b/server/debugger.c index ba08bd2fde9..04276464e7e 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -72,12 +72,8 @@ static const struct object_ops debug_event_ops = remove_queue, /* remove_queue */ debug_event_signaled, /* signaled */ no_satisfied, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ debug_event_destroy /* destroy */ }; @@ -93,12 +89,8 @@ static const struct object_ops debug_ctx_ops = remove_queue, /* remove_queue */ debug_ctx_signaled, /* signaled */ no_satisfied, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ debug_ctx_destroy /* destroy */ }; diff --git a/server/device.c b/server/device.c index 61ead6cb7d1..939e6c8651c 100644 --- a/server/device.c +++ b/server/device.c @@ -53,12 +53,8 @@ static const struct object_ops device_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ device_get_info, /* get_file_info */ - NULL, /* queue_async */ no_destroy /* destroy */ }; diff --git a/server/event.c b/server/event.c index b223487f073..927e2c77ed7 100644 --- a/server/event.c +++ b/server/event.c @@ -50,12 +50,8 @@ static const struct object_ops event_ops = remove_queue, /* remove_queue */ event_signaled, /* signaled */ event_satisfied, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ no_destroy /* destroy */ }; diff --git a/server/fd.c b/server/fd.c new file mode 100644 index 00000000000..1dff6efe80c --- /dev/null +++ b/server/fd.c @@ -0,0 +1,244 @@ +/* + * Server-side file descriptor management + * + * Copyright (C) 2003 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "config.h" + +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#include "object.h" +#include "file.h" +#include "handle.h" +#include "process.h" +#include "request.h" + +struct fd +{ + struct object obj; /* object header */ + const struct fd_ops *fd_ops; /* file descriptor operations */ + struct object *user; /* object using this file descriptor */ + int unix_fd; /* unix file descriptor */ + int mode; /* file protection mode */ +}; + +static void fd_dump( struct object *obj, int verbose ); +static void fd_destroy( struct object *obj ); + +static const struct object_ops fd_ops = +{ + sizeof(struct fd), /* size */ + fd_dump, /* dump */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + default_get_fd, /* get_fd */ + no_get_file_info, /* get_file_info */ + fd_destroy /* destroy */ +}; + + +static void fd_dump( struct object *obj, int verbose ) +{ + struct fd *fd = (struct fd *)obj; + fprintf( stderr, "Fd unix_fd=%d mode=%06o user=%p\n", fd->unix_fd, fd->mode, fd->user ); +} + +static void fd_destroy( struct object *obj ) +{ +#if 0 + struct fd *fd = (struct fd *)obj; + close( fd->unix_fd ); +#endif +} + +/* allocate an object that has an associated fd */ +void *alloc_fd_object( const struct object_ops *ops, + const struct fd_ops *fd_user_ops, int unix_fd ) +{ + struct object *user; + struct fd *fd = alloc_object( &fd_ops, -1 ); + + if (!fd) return NULL; + if (!(user = alloc_object( ops, unix_fd ))) + { + release_object( fd ); + return NULL; + } + fd->fd_ops = fd_user_ops; + fd->user = user; + fd->unix_fd = unix_fd; + fd->mode = 0; + + user->fd_obj = fd; + return user; +} + +/* retrieve the unix fd for an object */ +int get_unix_fd( struct object *obj ) +{ + struct fd *fd = obj->ops->get_fd( obj ); + int unix_fd = -1; + + if (fd) + { + unix_fd = fd->unix_fd; + release_object( fd ); + } + return unix_fd; +} + +/* set the unix fd for an object; can only be done once */ +void set_unix_fd( struct object *obj, int unix_fd ) +{ + struct fd *fd = obj->fd_obj; + + assert( fd ); + assert( fd->unix_fd == -1 ); + + fd->unix_fd = unix_fd; + obj->fd = unix_fd; +} + +/* close a file descriptor */ +void close_fd( struct fd *fd ) +{ + release_object( fd ); +} + +/* callback for event happening in the main poll() loop */ +void fd_poll_event( struct object *obj, int event ) +{ + struct fd *fd = obj->fd_obj; + return fd->fd_ops->poll_event( fd->user, event ); +} + +/* default add_queue() routine for objects that poll() on an fd */ +int default_fd_add_queue( struct object *obj, struct wait_queue_entry *entry ) +{ + struct fd *fd = obj->fd_obj; + + if (!obj->head) /* first on the queue */ + set_select_events( obj, fd->fd_ops->get_poll_events( fd->user ) ); + add_queue( obj, entry ); + return 1; +} + +/* default remove_queue() routine for objects that poll() on an fd */ +void default_fd_remove_queue( struct object *obj, struct wait_queue_entry *entry ) +{ + grab_object( obj ); + remove_queue( obj, entry ); + if (!obj->head) /* last on the queue is gone */ + set_select_events( obj, 0 ); + release_object( obj ); +} + +/* default signaled() routine for objects that poll() on an fd */ +int default_fd_signaled( struct object *obj, struct thread *thread ) +{ + struct fd *fd = obj->fd_obj; + int events = fd->fd_ops->get_poll_events( obj ); + + if (check_select_events( fd->unix_fd, events )) + { + /* stop waiting on select() if we are signaled */ + set_select_events( obj, 0 ); + return 1; + } + /* restart waiting on select() if we are no longer signaled */ + if (obj->head) set_select_events( obj, events ); + return 0; +} + +/* default flush() routine */ +int no_flush( struct object *obj ) +{ + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + return 0; +} + +/* default queue_async() routine */ +void no_queue_async( struct object *obj, void* ptr, unsigned int status, int type, int count ) +{ + set_error( STATUS_OBJECT_TYPE_MISMATCH ); +} + +/* same as get_handle_obj but retrieve the struct fd associated to the object */ +static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handle, + unsigned int access ) +{ + struct fd *fd = NULL; + struct object *obj; + + if ((obj = get_handle_obj( process, handle, 0, NULL ))) + { + if (obj->fd_obj) fd = (struct fd *)grab_object( obj->fd_obj ); + else set_error( STATUS_OBJECT_TYPE_MISMATCH ); + release_object( obj ); + } + return fd; +} + + +/* flush a file buffers */ +DECL_HANDLER(flush_file) +{ + struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 ); + + if (fd) + { + fd->fd_ops->flush( fd->user ); + release_object( fd ); + } +} + +/* create / reschedule an async I/O */ +DECL_HANDLER(register_async) +{ + struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 ); + +/* + * The queue_async method must do the following: + * + * 1. Get the async_queue for the request of given type. + * 2. Call find_async() to look for the specific client request in the queue (=> NULL if not found). + * 3. If status is STATUS_PENDING: + * a) If no async request found in step 2 (new request): call create_async() to initialize one. + * b) Set request's status to STATUS_PENDING. + * c) If the "queue" field of the async request is NULL: call async_insert() to put it into the queue. + * Otherwise: + * If the async request was found in step 2, destroy it by calling destroy_async(). + * 4. Carry out any operations necessary to adjust the object's poll events + * Usually: set_elect_events (obj, obj->ops->get_poll_events()). + * + * See also the implementations in file.c, serial.c, and sock.c. +*/ + + if (fd) + { + fd->fd_ops->queue_async( fd->user, req->overlapped, req->status, req->type, req->count ); + release_object( fd ); + } +} diff --git a/server/file.c b/server/file.c index b302fe67f1b..b4560a82a74 100644 --- a/server/file.c +++ b/server/file.c @@ -40,6 +40,7 @@ #include "winerror.h" #include "winbase.h" +#include "file.h" #include "handle.h" #include "thread.h" #include "request.h" @@ -65,7 +66,6 @@ static struct file *file_hash[NAME_HASH_SIZE]; static void file_dump( struct object *obj, int verbose ); static int file_get_poll_events( struct object *obj ); static void file_poll_event( struct object *obj, int event ); -static int file_get_fd( struct object *obj ); static int file_flush( struct object *obj ); static int file_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ); static void file_destroy( struct object *obj ); @@ -75,20 +75,24 @@ static const struct object_ops file_ops = { sizeof(struct file), /* size */ file_dump, /* dump */ - default_poll_add_queue, /* add_queue */ - default_poll_remove_queue, /* remove_queue */ - default_poll_signaled, /* signaled */ + default_fd_add_queue, /* add_queue */ + default_fd_remove_queue, /* remove_queue */ + default_fd_signaled, /* signaled */ no_satisfied, /* satisfied */ + default_get_fd, /* get_fd */ + file_get_info, /* get_file_info */ + file_destroy /* destroy */ +}; + +static const struct fd_ops file_fd_ops = +{ file_get_poll_events, /* get_poll_events */ file_poll_event, /* poll_event */ - file_get_fd, /* get_fd */ file_flush, /* flush */ file_get_info, /* get_file_info */ - file_queue_async, /* queue_async */ - file_destroy /* destroy */ + file_queue_async /* queue_async */ }; - static int get_name_hash( const char *name ) { int hash = 0; @@ -127,7 +131,8 @@ static struct file *create_file_for_fd( int fd, unsigned int access, unsigned in unsigned int attrs, int drive_type ) { struct file *file; - if ((file = alloc_object( &file_ops, fd ))) + + if ((file = alloc_fd_object( &file_ops, &file_fd_ops, fd ))) { file->name = NULL; file->next = NULL; @@ -291,22 +296,10 @@ static void file_poll_event( struct object *obj, int event ) } -static int file_get_fd( struct object *obj ) -{ - struct file *file = (struct file *)obj; - assert( obj->ops == &file_ops ); - return file->obj.fd; -} - static int file_flush( struct object *obj ) { - int ret; - struct file *file = (struct file *)grab_object(obj); - assert( obj->ops == &file_ops ); - - ret = (fsync( file->obj.fd ) != -1); + int ret = (fsync( get_unix_fd(obj) ) != -1); if (!ret) file_set_error(); - release_object( file ); return ret; } @@ -314,17 +307,17 @@ static int file_get_info( struct object *obj, struct get_file_info_reply *reply, { struct stat st; struct file *file = (struct file *)obj; - assert( obj->ops == &file_ops ); + int unix_fd = get_unix_fd( obj ); if (reply) { - if (fstat( file->obj.fd, &st ) == -1) + if (fstat( unix_fd, &st ) == -1) { file_set_error(); return FD_TYPE_INVALID; } if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) || - S_ISSOCK(st.st_mode) || isatty(file->obj.fd)) reply->type = FILE_TYPE_CHAR; + S_ISSOCK(st.st_mode) || isatty(unix_fd)) reply->type = FILE_TYPE_CHAR; else reply->type = FILE_TYPE_DISK; if (S_ISDIR(st.st_mode)) reply->attr = FILE_ATTRIBUTE_DIRECTORY; else reply->attr = FILE_ATTRIBUTE_ARCHIVE; @@ -394,7 +387,7 @@ static void file_queue_async(struct object *obj, void *ptr, unsigned int status, async_insert( q, async ); /* Check if the new pending request can be served immediately */ - pfd.fd = obj->fd; + pfd.fd = get_unix_fd( obj ); pfd.events = file_get_poll_events ( obj ); pfd.revents = 0; poll ( &pfd, 1, 0 ); @@ -469,7 +462,7 @@ static int set_file_pointer( obj_handle_t handle, unsigned int *low, int *high, xto = *low+((off_t)*high<<32); if (!(file = get_file_obj( current->process, handle, 0 ))) return 0; - if ((result = lseek(file->obj.fd,xto,whence))==-1) + if ((result = lseek( get_unix_fd(&file->obj), xto, whence))==-1) { /* Check for seek before start of file */ @@ -492,13 +485,14 @@ static int set_file_pointer( obj_handle_t handle, unsigned int *low, int *high, static int extend_file( struct file *file, off_t size ) { static const char zero; + int unix_fd = get_unix_fd( &file->obj ); /* extend the file one byte beyond the requested size and then truncate it */ /* this should work around ftruncate implementations that can't extend files */ - if ((lseek( file->obj.fd, size, SEEK_SET ) != -1) && - (write( file->obj.fd, &zero, 1 ) != -1)) + if ((lseek( unix_fd, size, SEEK_SET ) != -1) && + (write( unix_fd, &zero, 1 ) != -1)) { - ftruncate( file->obj.fd, size ); + ftruncate( unix_fd, size ); return 1; } file_set_error(); @@ -509,16 +503,17 @@ static int extend_file( struct file *file, off_t size ) static int truncate_file( struct file *file ) { int ret = 0; - off_t pos = lseek( file->obj.fd, 0, SEEK_CUR ); - off_t eof = lseek( file->obj.fd, 0, SEEK_END ); + int unix_fd = get_unix_fd( &file->obj ); + off_t pos = lseek( unix_fd, 0, SEEK_CUR ); + off_t eof = lseek( unix_fd, 0, SEEK_END ); if (eof < pos) ret = extend_file( file, pos ); else { - if (ftruncate( file->obj.fd, pos ) != -1) ret = 1; + if (ftruncate( unix_fd, pos ) != -1) ret = 1; else file_set_error(); } - lseek( file->obj.fd, pos, SEEK_SET ); /* restore file pos */ + lseek( unix_fd, pos, SEEK_SET ); /* restore file pos */ return ret; } @@ -527,17 +522,18 @@ int grow_file( struct file *file, int size_high, int size_low ) { int ret = 0; struct stat st; + int unix_fd = get_unix_fd( &file->obj ); off_t old_pos, size = size_low + (((off_t)size_high)<<32); - if (fstat( file->obj.fd, &st ) == -1) + if (fstat( unix_fd, &st ) == -1) { file_set_error(); return 0; } if (st.st_size >= size) return 1; /* already large enough */ - old_pos = lseek( file->obj.fd, 0, SEEK_CUR ); /* save old pos */ + old_pos = lseek( unix_fd, 0, SEEK_CUR ); /* save old pos */ ret = extend_file( file, size ); - lseek( file->obj.fd, old_pos, SEEK_SET ); /* restore file pos */ + lseek( unix_fd, old_pos, SEEK_SET ); /* restore file pos */ return ret; } @@ -633,8 +629,8 @@ DECL_HANDLER(get_handle_fd) if (fd != -1) reply->fd = fd; else if (!get_error()) { - if ((fd = obj->ops->get_fd( obj )) != -1) - send_client_fd( current->process, fd, req->handle ); + int unix_fd = get_unix_fd( obj ); + if (unix_fd != -1) send_client_fd( current->process, unix_fd, req->handle ); } reply->type = obj->ops->get_file_info( obj, NULL, &reply->flags ); release_object( obj ); @@ -663,18 +659,6 @@ DECL_HANDLER(truncate_file) } } -/* flush a file buffers */ -DECL_HANDLER(flush_file) -{ - struct object *obj; - - if ((obj = get_handle_obj( current->process, req->handle, 0, NULL ))) - { - obj->ops->flush( obj ); - release_object( obj ); - } -} - /* set a file access and modification times */ DECL_HANDLER(set_file_time) { diff --git a/server/file.h b/server/file.h new file mode 100644 index 00000000000..f5c9a32c308 --- /dev/null +++ b/server/file.h @@ -0,0 +1,56 @@ +/* + * Server-side file definitions + * + * Copyright (C) 2003 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_SERVER_FILE_H +#define __WINE_SERVER_FILE_H + +#include "object.h" + +struct fd; + +/* operations valid on file descriptor objects */ +struct fd_ops +{ + /* get the events we want to poll() for on this object */ + int (*get_poll_events)(struct object *); + /* a poll() event occured */ + void (*poll_event)(struct object *,int event); + /* flush the object buffers */ + int (*flush)(struct object *); + /* get file information */ + int (*get_file_info)(struct object *,struct get_file_info_reply *, int *flags); + /* queue an async operation - see register_async handler in async.c*/ + void (*queue_async)(struct object *, void* ptr, unsigned int status, int type, int count); +}; + +extern void *alloc_fd_object( const struct object_ops *ops, + const struct fd_ops *fd_user_ops, int unix_fd ); +extern int get_unix_fd( struct object *obj ); +extern void set_unix_fd( struct object *obj, int unix_fd ); +extern void close_fd( struct fd *fd ); +extern void fd_poll_event( struct object *obj, int event ); + +extern int default_fd_add_queue( struct object *obj, struct wait_queue_entry *entry ); +extern void default_fd_remove_queue( struct object *obj, struct wait_queue_entry *entry ); +extern int default_fd_signaled( struct object *obj, struct thread *thread ); +extern int no_flush( struct object *obj ); +extern void no_queue_async(struct object *obj, void* ptr, unsigned int status, int type, int count); + +#endif /* __WINE_SERVER_FILE_H */ diff --git a/server/handle.c b/server/handle.c index 9df42935535..471d5a7edee 100644 --- a/server/handle.c +++ b/server/handle.c @@ -104,12 +104,8 @@ static const struct object_ops handle_table_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ handle_table_destroy /* destroy */ }; diff --git a/server/hook.c b/server/hook.c index 3a483c18f29..d10318dca0f 100644 --- a/server/hook.c +++ b/server/hook.c @@ -66,12 +66,8 @@ static const struct object_ops hook_table_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ hook_table_destroy /* destroy */ }; diff --git a/server/mapping.c b/server/mapping.c index b7b055c6922..4881bc734d2 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -28,6 +28,7 @@ #include "winbase.h" +#include "file.h" #include "handle.h" #include "thread.h" #include "request.h" @@ -47,7 +48,7 @@ struct mapping struct mapping *shared_prev; /* prev in shared PE mapping list */ }; -static int mapping_get_fd( struct object *obj ); +static struct fd *mapping_get_fd( struct object *obj ); static int mapping_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ); static void mapping_dump( struct object *obj, int verbose ); static void mapping_destroy( struct object *obj ); @@ -60,12 +61,8 @@ static const struct object_ops mapping_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ mapping_get_fd, /* get_fd */ - no_flush, /* flush */ mapping_get_info, /* get_file_info */ - NULL, /* queue_async */ mapping_destroy /* destroy */ }; @@ -111,13 +108,7 @@ static void init_page_size(void) /* get the fd to use for mmaping a file */ inline static int get_mmap_fd( struct file *file ) { - struct object *obj; - if (!(obj = (struct object *)file)) - { - set_error( STATUS_INVALID_HANDLE ); - return -1; - } - return obj->ops->get_fd( obj ); + return get_unix_fd( (struct object *)file ); } /* find the shared PE mapping for a given mapping */ @@ -327,11 +318,12 @@ static void mapping_dump( struct object *obj, int verbose ) fputc( '\n', stderr ); } -static int mapping_get_fd( struct object *obj ) +static struct fd *mapping_get_fd( struct object *obj ) { struct mapping *mapping = (struct mapping *)obj; assert( obj->ops == &mapping_ops ); - return get_mmap_fd( mapping->file ); + + return default_get_fd( (struct object *)mapping->file ); } static int mapping_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ) diff --git a/server/mutex.c b/server/mutex.c index fe765534156..9ca844e3c8e 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -54,12 +54,8 @@ static const struct object_ops mutex_ops = remove_queue, /* remove_queue */ mutex_signaled, /* signaled */ mutex_satisfied, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ mutex_destroy /* destroy */ }; diff --git a/server/named_pipe.c b/server/named_pipe.c index fab8188d9b1..f2323cc5056 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -38,6 +38,7 @@ #include "winbase.h" +#include "file.h" #include "handle.h" #include "thread.h" #include "request.h" @@ -90,35 +91,35 @@ static const struct object_ops named_pipe_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ named_pipe_destroy /* destroy */ }; static void pipe_user_dump( struct object *obj, int verbose ); static void pipe_user_destroy( struct object *obj); -static int pipe_user_get_fd( struct object *obj ); static int pipe_user_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ); static const struct object_ops pipe_user_ops = { sizeof(struct pipe_user), /* size */ pipe_user_dump, /* dump */ - default_poll_add_queue, /* add_queue */ - default_poll_remove_queue, /* remove_queue */ - default_poll_signaled, /* signaled */ + default_fd_add_queue, /* add_queue */ + default_fd_remove_queue, /* remove_queue */ + default_fd_signaled, /* signaled */ no_satisfied, /* satisfied */ + default_get_fd, /* get_fd */ + pipe_user_get_info, /* get_file_info */ + pipe_user_destroy /* destroy */ +}; + +static const struct fd_ops pipe_user_fd_ops = +{ NULL, /* get_poll_events */ default_poll_event, /* poll_event */ - pipe_user_get_fd, /* get_fd */ no_flush, /* flush */ pipe_user_get_info, /* get_file_info */ - NULL, /* queue_async */ - pipe_user_destroy /* destroy */ + no_queue_async /* queue_async */ }; static void named_pipe_dump( struct object *obj, int verbose ) @@ -192,13 +193,6 @@ static void pipe_user_destroy( struct object *obj) release_object(user->pipe); } -static int pipe_user_get_fd( struct object *obj ) -{ - struct pipe_user *user = (struct pipe_user *)obj; - assert( obj->ops == &pipe_user_ops ); - return user->obj.fd; -} - static int pipe_user_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ) { if (reply) @@ -243,7 +237,7 @@ static struct pipe_user *create_pipe_user( struct named_pipe *pipe, int fd ) { struct pipe_user *user; - user = alloc_object( &pipe_user_ops, fd ); + user = alloc_fd_object( &pipe_user_ops, &pipe_user_fd_ops, fd ); if(!user) return NULL; @@ -475,4 +469,3 @@ DECL_HANDLER(get_named_pipe_info) release_object(user); } - diff --git a/server/object.c b/server/object.c index 600c04039d9..77e116243ae 100644 --- a/server/object.c +++ b/server/object.c @@ -28,6 +28,7 @@ #include <string.h> #include <unistd.h> +#include "file.h" #include "thread.h" #include "unicode.h" #include "list.h" @@ -137,6 +138,7 @@ void *alloc_object( const struct object_ops *ops, int fd ) if (obj) { obj->refcount = 1; + obj->fd_obj = NULL; obj->fd = fd; obj->select = -1; obj->ops = ops; @@ -218,6 +220,7 @@ void release_object( void *ptr ) assert( !obj->head ); assert( !obj->tail ); obj->ops->destroy( obj ); + if (obj->fd_obj) close_fd( obj->fd_obj ); if (obj->name) free_name( obj ); if (obj->select != -1) remove_select_user( obj ); if (obj->fd != -1) close( obj->fd ); @@ -287,16 +290,17 @@ int no_satisfied( struct object *obj, struct thread *thread ) return 0; /* not abandoned */ } -int no_get_fd( struct object *obj ) +struct fd *no_get_fd( struct object *obj ) { set_error( STATUS_OBJECT_TYPE_MISMATCH ); - return -1; + return NULL; } -int no_flush( struct object *obj ) +struct fd *default_get_fd( struct object *obj ) { + if (obj->fd_obj) return (struct fd *)grab_object( obj->fd_obj ); set_error( STATUS_OBJECT_TYPE_MISMATCH ); - return 0; + return NULL; } int no_get_file_info( struct object *obj, struct get_file_info_reply *info, int *flags ) @@ -310,41 +314,6 @@ void no_destroy( struct object *obj ) { } -/* default add_queue() routine for objects that poll() on an fd */ -int default_poll_add_queue( struct object *obj, struct wait_queue_entry *entry ) -{ - if (!obj->head) /* first on the queue */ - set_select_events( obj, obj->ops->get_poll_events( obj ) ); - add_queue( obj, entry ); - return 1; -} - -/* default remove_queue() routine for objects that poll() on an fd */ -void default_poll_remove_queue( struct object *obj, struct wait_queue_entry *entry ) -{ - grab_object(obj); - remove_queue( obj, entry ); - if (!obj->head) /* last on the queue is gone */ - set_select_events( obj, 0 ); - release_object( obj ); -} - -/* default signaled() routine for objects that poll() on an fd */ -int default_poll_signaled( struct object *obj, struct thread *thread ) -{ - int events = obj->ops->get_poll_events( obj ); - - if (check_select_events( obj->fd, events )) - { - /* stop waiting on select() if we are signaled */ - set_select_events( obj, 0 ); - return 1; - } - /* restart waiting on select() if we are no longer signaled */ - if (obj->head) set_select_events( obj, events ); - return 0; -} - /* default handler for poll() events */ void default_poll_event( struct object *obj, int event ) { diff --git a/server/object.h b/server/object.h index 711f5845e23..7868e2fbd73 100644 --- a/server/object.h +++ b/server/object.h @@ -55,18 +55,10 @@ struct object_ops int (*signaled)(struct object *,struct thread *); /* wait satisfied; return 1 if abandoned */ int (*satisfied)(struct object *,struct thread *); - /* get the events we want to poll() for on this object */ - int (*get_poll_events)(struct object *); - /* a poll() event occured */ - void (*poll_event)(struct object *,int event); - /* return a Unix fd that can be used to read/write from the object */ - int (*get_fd)(struct object *); - /* flush the object buffers */ - int (*flush)(struct object *); + /* return an fd object that can be used to read/write from the object */ + struct fd *(*get_fd)(struct object *); /* get file information */ int (*get_file_info)(struct object *,struct get_file_info_reply *, int *flags); - /* queue an async operation - see register_async handler in async.c*/ - void (*queue_async)(struct object *, void* ptr, unsigned int status, int type, int count); /* destroy on refcount == 0 */ void (*destroy)(struct object *); }; @@ -74,6 +66,7 @@ struct object_ops struct object { unsigned int refcount; /* reference count */ + struct fd *fd_obj; /* file descriptor */ int fd; /* file descriptor */ int select; /* select() user id */ const struct object_ops *ops; @@ -107,13 +100,10 @@ extern void release_object( void *obj ); extern struct object *find_object( const struct namespace *namespace, const WCHAR *name, size_t len ); extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry ); extern int no_satisfied( struct object *obj, struct thread *thread ); -extern int no_get_fd( struct object *obj ); -extern int no_flush( struct object *obj ); +extern struct fd *no_get_fd( struct object *obj ); +extern struct fd *default_get_fd( struct object *obj ); extern int no_get_file_info( struct object *obj, struct get_file_info_reply *info, int *flags ); extern void no_destroy( struct object *obj ); -extern int default_poll_add_queue( struct object *obj, struct wait_queue_entry *entry ); -extern void default_poll_remove_queue( struct object *obj, struct wait_queue_entry *entry ); -extern int default_poll_signaled( struct object *obj, struct thread *thread ); extern void default_poll_event( struct object *obj, int event ); #ifdef DEBUG_OBJECTS extern void dump_objects(void); diff --git a/server/pipe.c b/server/pipe.c index ce6f11a2036..4f57a2fdc8b 100644 --- a/server/pipe.c +++ b/server/pipe.c @@ -32,6 +32,7 @@ #include "winbase.h" +#include "file.h" #include "handle.h" #include "thread.h" #include "request.h" @@ -47,7 +48,7 @@ struct pipe static void pipe_dump( struct object *obj, int verbose ); static int pipe_get_poll_events( struct object *obj ); -static int pipe_get_fd( struct object *obj ); +static struct fd *pipe_get_fd( struct object *obj ); static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ); static void pipe_destroy( struct object *obj ); @@ -55,17 +56,22 @@ static const struct object_ops pipe_ops = { sizeof(struct pipe), /* size */ pipe_dump, /* dump */ - default_poll_add_queue, /* add_queue */ - default_poll_remove_queue, /* remove_queue */ - default_poll_signaled, /* signaled */ + default_fd_add_queue, /* add_queue */ + default_fd_remove_queue, /* remove_queue */ + default_fd_signaled, /* signaled */ no_satisfied, /* satisfied */ + pipe_get_fd, /* get_fd */ + pipe_get_info, /* get_file_info */ + pipe_destroy /* destroy */ +}; + +static const struct fd_ops pipe_fd_ops = +{ pipe_get_poll_events, /* get_poll_events */ default_poll_event, /* poll_event */ - pipe_get_fd, /* get_fd */ no_flush, /* flush */ pipe_get_info, /* get_file_info */ - NULL, /* queue_async */ - pipe_destroy /* destroy */ + no_queue_async /* queue_async */ }; @@ -73,7 +79,7 @@ static struct pipe *create_pipe_side( int fd, int side ) { struct pipe *pipe; - if ((pipe = alloc_object( &pipe_ops, fd ))) + if ((pipe = alloc_fd_object( &pipe_ops, &pipe_fd_ops, fd ))) { pipe->other = NULL; pipe->side = side; @@ -123,7 +129,7 @@ static int pipe_get_poll_events( struct object *obj ) return (pipe->side == READ_SIDE) ? POLLIN : POLLOUT; } -static int pipe_get_fd( struct object *obj ) +static struct fd *pipe_get_fd( struct object *obj ) { struct pipe *pipe = (struct pipe *)obj; assert( obj->ops == &pipe_ops ); @@ -131,9 +137,9 @@ static int pipe_get_fd( struct object *obj ) if (!pipe->other) { set_error( STATUS_PIPE_BROKEN ); - return -1; + return NULL; } - return pipe->obj.fd; + return (struct fd *)grab_object( pipe->obj.fd_obj ); } static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ) diff --git a/server/process.c b/server/process.c index 7d66d1b9eeb..8319129d65a 100644 --- a/server/process.c +++ b/server/process.c @@ -36,6 +36,7 @@ #include "winbase.h" #include "winnt.h" +#include "file.h" #include "handle.h" #include "process.h" #include "thread.h" @@ -62,13 +63,18 @@ static const struct object_ops process_ops = remove_queue, /* remove_queue */ process_signaled, /* signaled */ no_satisfied, /* satisfied */ + no_get_fd, /* get_fd */ + no_get_file_info, /* get_file_info */ + process_destroy /* destroy */ +}; + +static const struct fd_ops process_fd_ops = +{ NULL, /* get_poll_events */ process_poll_event, /* poll_event */ - no_get_fd, /* get_fd */ no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ - process_destroy /* destroy */ + no_queue_async /* queue_async */ }; /* process startup info */ @@ -102,12 +108,8 @@ static const struct object_ops startup_info_ops = remove_queue, /* remove_queue */ startup_info_signaled, /* signaled */ no_satisfied, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ startup_info_destroy /* destroy */ }; @@ -190,7 +192,7 @@ struct thread *create_process( int fd ) struct thread *thread = NULL; int request_pipe[2]; - if (!(process = alloc_object( &process_ops, fd ))) goto error; + if (!(process = alloc_fd_object( &process_ops, &process_fd_ops, fd ))) goto error; process->next = NULL; process->prev = NULL; process->parent = NULL; diff --git a/server/queue.c b/server/queue.c index 8eaba4d2a34..39c0d0ec956 100644 --- a/server/queue.c +++ b/server/queue.c @@ -143,12 +143,8 @@ static const struct object_ops msg_queue_ops = msg_queue_remove_queue, /* remove_queue */ msg_queue_signaled, /* signaled */ msg_queue_satisfied, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ msg_queue_destroy /* destroy */ }; @@ -161,12 +157,8 @@ static const struct object_ops thread_input_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ thread_input_destroy /* destroy */ }; diff --git a/server/registry.c b/server/registry.c index 31dfe97c4cf..5b75b50ebb1 100644 --- a/server/registry.c +++ b/server/registry.c @@ -37,7 +37,9 @@ #include <stdlib.h> #include <sys/stat.h> #include <unistd.h> + #include "object.h" +#include "file.h" #include "handle.h" #include "request.h" #include "unicode.h" @@ -166,12 +168,8 @@ static const struct object_ops key_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ key_destroy /* destroy */ }; @@ -1452,7 +1450,7 @@ static void load_registry( struct key *key, obj_handle_t handle ) int fd; if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL ))) return; - fd = dup(obj->ops->get_fd( obj )); + fd = dup( get_unix_fd( obj ) ); release_object( obj ); if (fd != -1) { @@ -1547,7 +1545,7 @@ static void save_registry( struct key *key, obj_handle_t handle ) return; } if (!(obj = get_handle_obj( current->process, handle, GENERIC_WRITE, NULL ))) return; - fd = dup(obj->ops->get_fd( obj )); + fd = dup( get_unix_fd( obj ) ); release_object( obj ); if (fd != -1) { diff --git a/server/request.c b/server/request.c index ff1450b0120..98bec45d8dd 100644 --- a/server/request.c +++ b/server/request.c @@ -48,6 +48,7 @@ #include "wincon.h" #include "wine/library.h" +#include "file.h" #include "handle.h" #include "thread.h" #include "process.h" @@ -81,13 +82,18 @@ static const struct object_ops master_socket_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ + no_get_fd, /* get_fd */ + no_get_file_info, /* get_file_info */ + no_destroy /* destroy */ +}; + +static const struct fd_ops master_socket_fd_ops = +{ NULL, /* get_poll_events */ master_socket_poll_event, /* poll_event */ - no_get_fd, /* get_fd */ no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ - no_destroy /* destroy */ + no_queue_async /* queue_async */ }; @@ -670,7 +676,7 @@ static void acquire_lock(void) chmod( server_socket_name, 0600 ); /* make sure no other user can connect */ if (listen( fd, 5 ) == -1) fatal_perror( "listen" ); - if (!(master_socket = alloc_object( &master_socket_ops, fd ))) + if (!(master_socket = alloc_fd_object( &master_socket_ops, &master_socket_fd_ops, fd ))) fatal_error( "out of memory\n" ); master_socket->timeout = NULL; set_select_events( &master_socket->obj, POLLIN ); diff --git a/server/select.c b/server/select.c index 9b70d04fc92..2ea23548184 100644 --- a/server/select.c +++ b/server/select.c @@ -28,7 +28,7 @@ #include <sys/types.h> #include <unistd.h> -#include "object.h" +#include "file.h" #include "thread.h" #include "process.h" @@ -301,7 +301,7 @@ void select_loop(void) { if (pollfd[i].revents) { - poll_users[i]->ops->poll_event( poll_users[i], pollfd[i].revents ); + fd_poll_event( poll_users[i], pollfd[i].revents ); if (!--ret) break; } } diff --git a/server/semaphore.c b/server/semaphore.c index ee9098855ef..3f5e9534d55 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -50,12 +50,8 @@ static const struct object_ops semaphore_ops = remove_queue, /* remove_queue */ semaphore_signaled, /* signaled */ semaphore_satisfied, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ no_destroy /* destroy */ }; diff --git a/server/serial.c b/server/serial.c index 22c336f977e..0e4d79f4ff5 100644 --- a/server/serial.c +++ b/server/serial.c @@ -39,13 +39,13 @@ #include "winerror.h" #include "winbase.h" +#include "file.h" #include "handle.h" #include "thread.h" #include "request.h" #include "async.h" static void serial_dump( struct object *obj, int verbose ); -static int serial_get_fd( struct object *obj ); static int serial_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ); static int serial_get_poll_events( struct object *obj ); static void serial_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count); @@ -82,17 +82,22 @@ static const struct object_ops serial_ops = { sizeof(struct serial), /* size */ serial_dump, /* dump */ - default_poll_add_queue, /* add_queue */ - default_poll_remove_queue, /* remove_queue */ - default_poll_signaled, /* signaled */ + default_fd_add_queue, /* add_queue */ + default_fd_remove_queue, /* remove_queue */ + default_fd_signaled, /* signaled */ no_satisfied, /* satisfied */ + default_get_fd, /* get_fd */ + serial_get_info, /* get_file_info */ + destroy_serial /* destroy */ +}; + +static const struct fd_ops serial_fd_ops = +{ serial_get_poll_events, /* get_poll_events */ serial_poll_event, /* poll_event */ - serial_get_fd, /* get_fd */ serial_flush, /* flush */ serial_get_info, /* get_file_info */ - serial_queue_async, /* queue_async */ - destroy_serial /* destroy */ + serial_queue_async /* queue_async */ }; static struct serial *create_serial( const char *nameptr, size_t len, unsigned int access, int attributes ) @@ -137,7 +142,7 @@ static struct serial *create_serial( const char *nameptr, size_t len, unsigned i if(0>fcntl(fd, F_SETFL, 0)) perror("fcntl"); - if ((serial = alloc_object( &serial_ops, fd ))) + if ((serial = alloc_fd_object( &serial_ops, &serial_fd_ops, fd ))) { serial->attrib = attributes; serial->access = access; @@ -194,13 +199,6 @@ static int serial_get_poll_events( struct object *obj ) return events; } -static int serial_get_fd( struct object *obj ) -{ - struct serial *serial = (struct serial *)obj; - assert( obj->ops == &serial_ops ); - return serial->obj.fd; -} - static int serial_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ) { struct serial *serial = (struct serial *) obj; @@ -245,7 +243,7 @@ static void serial_poll_event(struct object *obj, int event) if(IS_READY(serial->wait_q) && (POLLIN & event) ) async_notify(serial->wait_q.head,STATUS_ALERTED); - set_select_events(obj,obj->ops->get_poll_events(obj)); + set_select_events( obj, serial_get_poll_events(obj) ); } static void serial_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count) @@ -295,7 +293,7 @@ static void serial_queue_async(struct object *obj, void *ptr, unsigned int statu } /* Check if the new pending request can be served immediately */ - pfd.fd = obj->fd; + pfd.fd = get_unix_fd( obj ); pfd.events = serial_get_poll_events ( obj ); pfd.revents = 0; poll ( &pfd, 1, 0 ); @@ -315,16 +313,11 @@ static void serial_queue_async(struct object *obj, void *ptr, unsigned int statu static int serial_flush( struct object *obj ) { - int ret; - struct serial *serial = (struct serial *)grab_object(obj); - assert( obj->ops == &serial_ops ); - /* MSDN says: If hFile is a handle to a communications device, * the function only flushes the transmit buffer. */ - ret = (tcflush( serial->obj.fd, TCOFLUSH ) != -1); + int ret = (tcflush( get_unix_fd(obj), TCOFLUSH ) != -1); if (!ret) file_set_error(); - release_object( serial ); return ret; } diff --git a/server/smb.c b/server/smb.c index e9247746cd4..ab00685f235 100644 --- a/server/smb.c +++ b/server/smb.c @@ -40,12 +40,12 @@ #include "winerror.h" #include "winbase.h" +#include "file.h" #include "handle.h" #include "thread.h" #include "request.h" static void smb_dump( struct object *obj, int verbose ); -static int smb_get_fd( struct object *obj ); static int smb_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ); static int smb_get_poll_events( struct object *obj ); static void destroy_smb(struct object *obj); @@ -64,17 +64,22 @@ static const struct object_ops smb_ops = { sizeof(struct smb), /* size */ smb_dump, /* dump */ - default_poll_add_queue, /* add_queue */ - default_poll_remove_queue, /* remove_queue */ - default_poll_signaled, /* signaled */ + default_fd_add_queue, /* add_queue */ + default_fd_remove_queue, /* remove_queue */ + default_fd_signaled, /* signaled */ no_satisfied, /* satisfied */ + default_get_fd, /* get_fd */ + smb_get_info, /* get_file_info */ + destroy_smb /* destroy */ +}; + +static const struct fd_ops smb_fd_ops = +{ smb_get_poll_events, /* get_poll_events */ default_poll_event, /* poll_event */ - smb_get_fd, /* get_fd */ no_flush, /* flush */ smb_get_info, /* get_file_info */ - NULL, /* queue_async */ - destroy_smb /* destroy */ + no_queue_async /* queue_async */ }; static void destroy_smb( struct object *obj) @@ -108,13 +113,6 @@ static int smb_get_poll_events( struct object *obj ) return events; } -static int smb_get_fd( struct object *obj ) -{ - struct smb *smb = (struct smb *)obj; - assert( obj->ops == &smb_ops ); - return smb->obj.fd; -} - static int smb_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ) { /* struct smb *smb = (struct smb *) obj; */ @@ -154,7 +152,7 @@ DECL_HANDLER(create_smb) return; } - smb = alloc_object( &smb_ops, fd ); + smb = alloc_fd_object( &smb_ops, &smb_fd_ops, fd ); if (smb) { smb->tree_id = req->tree_id; diff --git a/server/snapshot.c b/server/snapshot.c index 0df1ac42106..90a8bf4ed0b 100644 --- a/server/snapshot.c +++ b/server/snapshot.c @@ -61,12 +61,8 @@ static const struct object_ops snapshot_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ snapshot_destroy /* destroy */ }; diff --git a/server/sock.c b/server/sock.c index 05324b9ef17..d528ab5ebdc 100644 --- a/server/sock.c +++ b/server/sock.c @@ -44,9 +44,10 @@ #include <time.h> #include <unistd.h> -#include "winerror.h" #include "winbase.h" + #include "process.h" +#include "file.h" #include "handle.h" #include "thread.h" #include "request.h" @@ -83,7 +84,6 @@ static void sock_dump( struct object *obj, int verbose ); static int sock_signaled( struct object *obj, struct thread *thread ); static int sock_get_poll_events( struct object *obj ); static void sock_poll_event( struct object *obj, int event ); -static int sock_get_fd( struct object *obj ); static int sock_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ); static void sock_destroy( struct object *obj ); static int sock_get_error( int err ); @@ -98,13 +98,18 @@ static const struct object_ops sock_ops = remove_queue, /* remove_queue */ sock_signaled, /* signaled */ no_satisfied, /* satisfied */ + default_get_fd, /* get_fd */ + sock_get_info, /* get_file_info */ + sock_destroy /* destroy */ +}; + +static const struct fd_ops sock_fd_ops = +{ sock_get_poll_events, /* get_poll_events */ sock_poll_event, /* poll_event */ - sock_get_fd, /* get_fd */ no_flush, /* flush */ sock_get_info, /* get_file_info */ - sock_queue_async, /* queue_async */ - sock_destroy /* destroy */ + sock_queue_async /* queue_async */ }; @@ -438,7 +443,7 @@ static int sock_signaled( struct object *obj, struct thread *thread ) struct sock *sock = (struct sock *)obj; assert( obj->ops == &sock_ops ); - return check_select_events( sock->obj.fd, sock_get_poll_events( &sock->obj ) ); + return check_select_events( get_unix_fd(obj), sock_get_poll_events( &sock->obj ) ); } static int sock_get_poll_events( struct object *obj ) @@ -467,13 +472,6 @@ static int sock_get_poll_events( struct object *obj ) return ev; } -static int sock_get_fd( struct object *obj ) -{ - struct sock *sock = (struct sock *)obj; - assert( obj->ops == &sock_ops ); - return sock->obj.fd; -} - static int sock_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ) { struct sock *sock = (struct sock*) obj; @@ -592,8 +590,8 @@ static struct object *create_socket( int family, int type, int protocol, unsigne return NULL; } fcntl(sockfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */ - if (!(sock = alloc_object( &sock_ops, -1 ))) return NULL; - sock->obj.fd = sockfd; + if (!(sock = alloc_fd_object( &sock_ops, &sock_fd_ops, -1 ))) return NULL; + set_unix_fd( &sock->obj, sockfd ); sock->state = (type != SOCK_STREAM) ? (FD_READ|FD_WRITE) : 0; sock->mask = 0; sock->hmask = 0; @@ -640,13 +638,13 @@ static struct sock *accept_socket( obj_handle_t handle ) * return. */ slen = sizeof(saddr); - acceptfd = accept(sock->obj.fd,&saddr,&slen); + acceptfd = accept( get_unix_fd(&sock->obj), &saddr, &slen); if (acceptfd==-1) { sock_set_error(); release_object( sock ); return NULL; } - if (!(acceptsock = alloc_object( &sock_ops, -1 ))) + if (!(acceptsock = alloc_fd_object( &sock_ops, &sock_fd_ops, acceptfd ))) { release_object( sock ); return NULL; @@ -654,7 +652,6 @@ static struct sock *accept_socket( obj_handle_t handle ) /* newly created socket gets the same properties of the listening socket */ fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */ - acceptsock->obj.fd = acceptfd; acceptsock->state = FD_WINE_CONNECTED|FD_READ|FD_WRITE; if (sock->state & FD_WINE_NONBLOCKING) acceptsock->state |= FD_WINE_NONBLOCKING; diff --git a/server/thread.c b/server/thread.c index f8396e09436..dceeef4e679 100644 --- a/server/thread.c +++ b/server/thread.c @@ -35,6 +35,7 @@ #include "winbase.h" +#include "file.h" #include "handle.h" #include "process.h" #include "thread.h" @@ -86,13 +87,18 @@ static const struct object_ops thread_ops = remove_queue, /* remove_queue */ thread_signaled, /* signaled */ no_satisfied, /* satisfied */ + no_get_fd, /* get_fd */ + no_get_file_info, /* get_file_info */ + destroy_thread /* destroy */ +}; + +static const struct fd_ops thread_fd_ops = +{ NULL, /* get_poll_events */ thread_poll_event, /* poll_event */ - no_get_fd, /* get_fd */ no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ - destroy_thread /* destroy */ + no_queue_async /* queue_async */ }; static struct thread *first_thread; @@ -144,7 +150,7 @@ struct thread *create_thread( int fd, struct process *process ) { struct thread *thread; - if (!(thread = alloc_object( &thread_ops, fd ))) return NULL; + if (!(thread = alloc_fd_object( &thread_ops, &thread_fd_ops, fd ))) return NULL; init_thread_structure( thread ); diff --git a/server/timer.c b/server/timer.c index ddc137d4fc2..2d48fc6be65 100644 --- a/server/timer.c +++ b/server/timer.c @@ -57,12 +57,8 @@ static const struct object_ops timer_ops = remove_queue, /* remove_queue */ timer_signaled, /* signaled */ timer_satisfied, /* satisfied */ - NULL, /* get_poll_events */ - NULL, /* poll_event */ no_get_fd, /* get_fd */ - no_flush, /* flush */ no_get_file_info, /* get_file_info */ - NULL, /* queue_async */ timer_destroy /* destroy */ }; -- GitLab