Started moving functions that deal with Unix file descriptors to a
separate fd object. This will be needed for file locking.
This commit is contained in:
parent
45adf0843f
commit
863637b158
|
@ -16,6 +16,7 @@ C_SRCS = \
|
|||
debugger.c \
|
||||
device.c \
|
||||
event.c \
|
||||
fd.c \
|
||||
file.c \
|
||||
handle.c \
|
||||
hook.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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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,19 +75,23 @@ 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 */
|
||||
file_get_poll_events, /* get_poll_events */
|
||||
file_poll_event, /* poll_event */
|
||||
file_get_fd, /* get_fd */
|
||||
file_flush, /* flush */
|
||||
default_get_fd, /* get_fd */
|
||||
file_get_info, /* get_file_info */
|
||||
file_queue_async, /* queue_async */
|
||||
file_destroy /* destroy */
|
||||
};
|
||||
|
||||
static const struct fd_ops file_fd_ops =
|
||||
{
|
||||
file_get_poll_events, /* get_poll_events */
|
||||
file_poll_event, /* poll_event */
|
||||
file_flush, /* flush */
|
||||
file_get_info, /* get_file_info */
|
||||
file_queue_async /* queue_async */
|
||||
};
|
||||
|
||||
static int get_name_hash( const char *name )
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
28
server/smb.c
28
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;
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue