Don't cache file descriptors open on removable devices.
This commit is contained in:
parent
bc22e2f03d
commit
f62f6e8fe1
|
@ -403,8 +403,7 @@ static int receive_fd( obj_handle_t *handle )
|
|||
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
|
||||
fd = cmsg.fd;
|
||||
#endif
|
||||
if (fd == -1) server_protocol_error( "no fd received for handle %d\n", *handle );
|
||||
fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
|
||||
if (fd != -1) fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
|
||||
return fd;
|
||||
}
|
||||
if (!ret) break;
|
||||
|
@ -417,41 +416,6 @@ static int receive_fd( obj_handle_t *handle )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* store_cached_fd
|
||||
*
|
||||
* Store the cached fd value for a given handle back into the server.
|
||||
* Returns the new fd, which can be different if there was already an
|
||||
* fd in the cache for that handle.
|
||||
*/
|
||||
inline static int store_cached_fd( int *fd, obj_handle_t handle )
|
||||
{
|
||||
int ret;
|
||||
|
||||
SERVER_START_REQ( set_handle_cached_fd )
|
||||
{
|
||||
req->handle = handle;
|
||||
req->fd = *fd;
|
||||
if (!(ret = wine_server_call( req )))
|
||||
{
|
||||
if (reply->cur_fd != *fd)
|
||||
{
|
||||
/* someone was here before us */
|
||||
close( *fd );
|
||||
*fd = reply->cur_fd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
close( *fd );
|
||||
*fd = -1;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* wine_server_fd_to_handle (NTDLL.@)
|
||||
*
|
||||
|
@ -502,7 +466,7 @@ int wine_server_fd_to_handle( int fd, unsigned int access, int inherit, obj_hand
|
|||
int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd, int *flags )
|
||||
{
|
||||
obj_handle_t fd_handle;
|
||||
int ret, fd = -1;
|
||||
int ret, removable = -1, fd = -1;
|
||||
|
||||
*unix_fd = -1;
|
||||
for (;;)
|
||||
|
@ -511,8 +475,12 @@ int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *uni
|
|||
{
|
||||
req->handle = handle;
|
||||
req->access = access;
|
||||
if (!(ret = wine_server_call( req ))) fd = reply->fd;
|
||||
if (flags) *flags = reply->flags;
|
||||
if (!(ret = wine_server_call( req )))
|
||||
{
|
||||
fd = reply->fd;
|
||||
removable = reply->removable;
|
||||
if (flags) *flags = reply->flags;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret) return ret;
|
||||
|
@ -521,8 +489,39 @@ int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *uni
|
|||
|
||||
/* it wasn't in the cache, get it from the server */
|
||||
fd = receive_fd( &fd_handle );
|
||||
if (fd == -1) return STATUS_TOO_MANY_OPENED_FILES;
|
||||
if (fd_handle != handle) removable = -1;
|
||||
|
||||
if (removable == -1)
|
||||
{
|
||||
FILE_FS_DEVICE_INFORMATION info;
|
||||
if (FILE_GetDeviceInfo( fd, &info ) == STATUS_SUCCESS)
|
||||
removable = (info.Characteristics & FILE_REMOVABLE_MEDIA) != 0;
|
||||
}
|
||||
else if (removable) break; /* don't cache it */
|
||||
|
||||
/* and store it back into the cache */
|
||||
ret = store_cached_fd( &fd, fd_handle );
|
||||
SERVER_START_REQ( set_handle_fd )
|
||||
{
|
||||
req->handle = handle;
|
||||
req->fd = fd;
|
||||
req->removable = removable;
|
||||
if (!(ret = wine_server_call( req )))
|
||||
{
|
||||
if (reply->cur_fd != fd && reply->cur_fd != -1)
|
||||
{
|
||||
/* someone was here before us */
|
||||
close( fd );
|
||||
fd = reply->cur_fd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
close( fd );
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret) return ret;
|
||||
|
||||
if (fd_handle == handle) break;
|
||||
|
|
|
@ -538,20 +538,6 @@ struct set_handle_info_reply
|
|||
|
||||
|
||||
|
||||
struct set_handle_cached_fd_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t handle;
|
||||
int fd;
|
||||
};
|
||||
struct set_handle_cached_fd_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
int cur_fd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct dup_handle_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -803,6 +789,7 @@ struct get_handle_fd_reply
|
|||
{
|
||||
struct reply_header __header;
|
||||
int fd;
|
||||
int removable;
|
||||
int flags;
|
||||
};
|
||||
#define FD_FLAG_OVERLAPPED 0x01
|
||||
|
@ -813,6 +800,20 @@ struct get_handle_fd_reply
|
|||
* only handle available data (don't wait) */
|
||||
|
||||
|
||||
struct set_handle_fd_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t handle;
|
||||
int fd;
|
||||
int removable;
|
||||
};
|
||||
struct set_handle_fd_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
int cur_fd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct flush_file_request
|
||||
{
|
||||
|
@ -3597,7 +3598,6 @@ enum request
|
|||
REQ_get_apc,
|
||||
REQ_close_handle,
|
||||
REQ_set_handle_info,
|
||||
REQ_set_handle_cached_fd,
|
||||
REQ_dup_handle,
|
||||
REQ_open_process,
|
||||
REQ_open_thread,
|
||||
|
@ -3614,6 +3614,7 @@ enum request
|
|||
REQ_create_file,
|
||||
REQ_alloc_file_handle,
|
||||
REQ_get_handle_fd,
|
||||
REQ_set_handle_fd,
|
||||
REQ_flush_file,
|
||||
REQ_lock_file,
|
||||
REQ_unlock_file,
|
||||
|
@ -3809,7 +3810,6 @@ union generic_request
|
|||
struct get_apc_request get_apc_request;
|
||||
struct close_handle_request close_handle_request;
|
||||
struct set_handle_info_request set_handle_info_request;
|
||||
struct set_handle_cached_fd_request set_handle_cached_fd_request;
|
||||
struct dup_handle_request dup_handle_request;
|
||||
struct open_process_request open_process_request;
|
||||
struct open_thread_request open_thread_request;
|
||||
|
@ -3826,6 +3826,7 @@ union generic_request
|
|||
struct create_file_request create_file_request;
|
||||
struct alloc_file_handle_request alloc_file_handle_request;
|
||||
struct get_handle_fd_request get_handle_fd_request;
|
||||
struct set_handle_fd_request set_handle_fd_request;
|
||||
struct flush_file_request flush_file_request;
|
||||
struct lock_file_request lock_file_request;
|
||||
struct unlock_file_request unlock_file_request;
|
||||
|
@ -4019,7 +4020,6 @@ union generic_reply
|
|||
struct get_apc_reply get_apc_reply;
|
||||
struct close_handle_reply close_handle_reply;
|
||||
struct set_handle_info_reply set_handle_info_reply;
|
||||
struct set_handle_cached_fd_reply set_handle_cached_fd_reply;
|
||||
struct dup_handle_reply dup_handle_reply;
|
||||
struct open_process_reply open_process_reply;
|
||||
struct open_thread_reply open_thread_reply;
|
||||
|
@ -4036,6 +4036,7 @@ union generic_reply
|
|||
struct create_file_reply create_file_reply;
|
||||
struct alloc_file_handle_reply alloc_file_handle_reply;
|
||||
struct get_handle_fd_reply get_handle_fd_reply;
|
||||
struct set_handle_fd_reply set_handle_fd_reply;
|
||||
struct flush_file_reply flush_file_reply;
|
||||
struct lock_file_reply lock_file_reply;
|
||||
struct unlock_file_reply unlock_file_reply;
|
||||
|
@ -4205,6 +4206,6 @@ union generic_reply
|
|||
struct set_mailslot_info_reply set_mailslot_info_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 190
|
||||
#define SERVER_PROTOCOL_VERSION 191
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
22
server/fd.c
22
server/fd.c
|
@ -176,6 +176,7 @@ struct device
|
|||
struct object obj; /* object header */
|
||||
struct list entry; /* entry in device hash list */
|
||||
dev_t dev; /* device number */
|
||||
int removable; /* removable device? (or -1 if unknown) */
|
||||
struct list inode_hash[INODE_HASH_SIZE]; /* inodes hash table */
|
||||
};
|
||||
|
||||
|
@ -595,6 +596,7 @@ static struct device *get_device( dev_t dev )
|
|||
if ((device = alloc_object( &device_ops )))
|
||||
{
|
||||
device->dev = dev;
|
||||
device->removable = -1;
|
||||
for (i = 0; i < INODE_HASH_SIZE; i++) list_init( &device->inode_hash[i] );
|
||||
list_add_head( &device_hash[hash], &device->entry );
|
||||
}
|
||||
|
@ -1648,11 +1650,31 @@ DECL_HANDLER(get_handle_fd)
|
|||
if (cached_fd != -1) reply->fd = cached_fd;
|
||||
else if (!get_error()) send_client_fd( current->process, unix_fd, req->handle );
|
||||
}
|
||||
if (fd->inode) reply->removable = fd->inode->device->removable;
|
||||
reply->flags = fd->fd_ops->get_file_info( fd );
|
||||
release_object( fd );
|
||||
}
|
||||
}
|
||||
|
||||
/* set the cached file descriptor of a handle */
|
||||
DECL_HANDLER(set_handle_fd)
|
||||
{
|
||||
struct fd *fd;
|
||||
|
||||
reply->cur_fd = -1;
|
||||
if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
|
||||
{
|
||||
struct device *device = fd->inode ? fd->inode->device : NULL;
|
||||
|
||||
if (device && device->removable == -1) device->removable = req->removable;
|
||||
|
||||
/* only cache the fd on non-removable devices */
|
||||
if (!device || !device->removable)
|
||||
reply->cur_fd = set_handle_unix_fd( current->process, req->handle, req->fd );
|
||||
release_object( fd );
|
||||
}
|
||||
}
|
||||
|
||||
/* get ready to unmount a Unix device */
|
||||
DECL_HANDLER(unmount_device)
|
||||
{
|
||||
|
|
|
@ -426,10 +426,11 @@ int get_handle_unix_fd( struct process *process, obj_handle_t handle, unsigned i
|
|||
}
|
||||
|
||||
/* set the cached fd for a handle if not set already, and return the current value */
|
||||
static int set_handle_unix_fd( struct process *process, obj_handle_t handle, int fd )
|
||||
int set_handle_unix_fd( struct process *process, obj_handle_t handle, int fd )
|
||||
{
|
||||
struct handle_entry *entry;
|
||||
|
||||
if (handle_is_global( handle )) return -1; /* no fd cache for global handles */
|
||||
if (!(entry = get_handle( process, handle ))) return -1;
|
||||
/* if no current fd set it, otherwise return current fd */
|
||||
if (entry->fd == -1) entry->fd = fd;
|
||||
|
@ -556,15 +557,6 @@ DECL_HANDLER(set_handle_info)
|
|||
reply->old_flags = set_handle_flags( current->process, req->handle, req->mask, req->flags );
|
||||
}
|
||||
|
||||
/* set the cached file descriptor of a handle */
|
||||
DECL_HANDLER(set_handle_cached_fd)
|
||||
{
|
||||
int fd = req->fd;
|
||||
|
||||
if (handle_is_global(req->handle)) fd = -1; /* no fd cache for global handles */
|
||||
reply->cur_fd = set_handle_unix_fd( current->process, req->handle, fd );
|
||||
}
|
||||
|
||||
/* duplicate a handle */
|
||||
DECL_HANDLER(dup_handle)
|
||||
{
|
||||
|
|
|
@ -40,6 +40,7 @@ extern struct object *get_handle_obj( struct process *process, obj_handle_t hand
|
|||
unsigned int access, const struct object_ops *ops );
|
||||
extern unsigned int get_handle_access( struct process *process, obj_handle_t handle );
|
||||
extern int get_handle_unix_fd( struct process *process, obj_handle_t handle, unsigned int access );
|
||||
extern int set_handle_unix_fd( struct process *process, obj_handle_t handle, int fd );
|
||||
extern obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, struct process *dst,
|
||||
unsigned int access, int inherit, int options );
|
||||
extern obj_handle_t open_object( const struct namespace *namespace, const WCHAR *name, size_t len,
|
||||
|
|
|
@ -442,15 +442,6 @@ enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC_IO };
|
|||
@END
|
||||
|
||||
|
||||
/* Set the cached file descriptor of a handle */
|
||||
@REQ(set_handle_cached_fd)
|
||||
obj_handle_t handle; /* handle we are interested in */
|
||||
int fd; /* file descriptor */
|
||||
@REPLY
|
||||
int cur_fd; /* current file descriptor */
|
||||
@END
|
||||
|
||||
|
||||
/* Duplicate a handle */
|
||||
@REQ(dup_handle)
|
||||
obj_handle_t src_process; /* src process handle */
|
||||
|
@ -621,6 +612,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
|
|||
unsigned int access; /* wanted access rights */
|
||||
@REPLY
|
||||
int fd; /* file descriptor */
|
||||
int removable; /* is device removable? (-1 if unknown) */
|
||||
int flags; /* file read/write flags (see below) */
|
||||
@END
|
||||
#define FD_FLAG_OVERLAPPED 0x01 /* fd opened in overlapped mode */
|
||||
|
@ -630,6 +622,15 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
|
|||
#define FD_FLAG_AVAILABLE 0x10 /* in overlap read/write operation,
|
||||
* only handle available data (don't wait) */
|
||||
|
||||
/* Set the cached file descriptor of a handle */
|
||||
@REQ(set_handle_fd)
|
||||
obj_handle_t handle; /* handle we are interested in */
|
||||
int fd; /* file descriptor */
|
||||
int removable; /* is device removable? (-1 if unknown) */
|
||||
@REPLY
|
||||
int cur_fd; /* current file descriptor */
|
||||
@END
|
||||
|
||||
|
||||
/* Flush a file buffers */
|
||||
@REQ(flush_file)
|
||||
|
|
|
@ -124,7 +124,6 @@ DECL_HANDLER(queue_apc);
|
|||
DECL_HANDLER(get_apc);
|
||||
DECL_HANDLER(close_handle);
|
||||
DECL_HANDLER(set_handle_info);
|
||||
DECL_HANDLER(set_handle_cached_fd);
|
||||
DECL_HANDLER(dup_handle);
|
||||
DECL_HANDLER(open_process);
|
||||
DECL_HANDLER(open_thread);
|
||||
|
@ -141,6 +140,7 @@ DECL_HANDLER(open_semaphore);
|
|||
DECL_HANDLER(create_file);
|
||||
DECL_HANDLER(alloc_file_handle);
|
||||
DECL_HANDLER(get_handle_fd);
|
||||
DECL_HANDLER(set_handle_fd);
|
||||
DECL_HANDLER(flush_file);
|
||||
DECL_HANDLER(lock_file);
|
||||
DECL_HANDLER(unlock_file);
|
||||
|
@ -335,7 +335,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_get_apc,
|
||||
(req_handler)req_close_handle,
|
||||
(req_handler)req_set_handle_info,
|
||||
(req_handler)req_set_handle_cached_fd,
|
||||
(req_handler)req_dup_handle,
|
||||
(req_handler)req_open_process,
|
||||
(req_handler)req_open_thread,
|
||||
|
@ -352,6 +351,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_create_file,
|
||||
(req_handler)req_alloc_file_handle,
|
||||
(req_handler)req_get_handle_fd,
|
||||
(req_handler)req_set_handle_fd,
|
||||
(req_handler)req_flush_file,
|
||||
(req_handler)req_lock_file,
|
||||
(req_handler)req_unlock_file,
|
||||
|
|
|
@ -836,17 +836,6 @@ static void dump_set_handle_info_reply( const struct set_handle_info_reply *req
|
|||
fprintf( stderr, " old_flags=%d", req->old_flags );
|
||||
}
|
||||
|
||||
static void dump_set_handle_cached_fd_request( const struct set_handle_cached_fd_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%p,", req->handle );
|
||||
fprintf( stderr, " fd=%d", req->fd );
|
||||
}
|
||||
|
||||
static void dump_set_handle_cached_fd_reply( const struct set_handle_cached_fd_reply *req )
|
||||
{
|
||||
fprintf( stderr, " cur_fd=%d", req->cur_fd );
|
||||
}
|
||||
|
||||
static void dump_dup_handle_request( const struct dup_handle_request *req )
|
||||
{
|
||||
fprintf( stderr, " src_process=%p,", req->src_process );
|
||||
|
@ -1047,9 +1036,22 @@ static void dump_get_handle_fd_request( const struct get_handle_fd_request *req
|
|||
static void dump_get_handle_fd_reply( const struct get_handle_fd_reply *req )
|
||||
{
|
||||
fprintf( stderr, " fd=%d,", req->fd );
|
||||
fprintf( stderr, " removable=%d,", req->removable );
|
||||
fprintf( stderr, " flags=%d", req->flags );
|
||||
}
|
||||
|
||||
static void dump_set_handle_fd_request( const struct set_handle_fd_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%p,", req->handle );
|
||||
fprintf( stderr, " fd=%d,", req->fd );
|
||||
fprintf( stderr, " removable=%d", req->removable );
|
||||
}
|
||||
|
||||
static void dump_set_handle_fd_reply( const struct set_handle_fd_reply *req )
|
||||
{
|
||||
fprintf( stderr, " cur_fd=%d", req->cur_fd );
|
||||
}
|
||||
|
||||
static void dump_flush_file_request( const struct flush_file_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%p", req->handle );
|
||||
|
@ -3109,7 +3111,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_get_apc_request,
|
||||
(dump_func)dump_close_handle_request,
|
||||
(dump_func)dump_set_handle_info_request,
|
||||
(dump_func)dump_set_handle_cached_fd_request,
|
||||
(dump_func)dump_dup_handle_request,
|
||||
(dump_func)dump_open_process_request,
|
||||
(dump_func)dump_open_thread_request,
|
||||
|
@ -3126,6 +3127,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_create_file_request,
|
||||
(dump_func)dump_alloc_file_handle_request,
|
||||
(dump_func)dump_get_handle_fd_request,
|
||||
(dump_func)dump_set_handle_fd_request,
|
||||
(dump_func)dump_flush_file_request,
|
||||
(dump_func)dump_lock_file_request,
|
||||
(dump_func)dump_unlock_file_request,
|
||||
|
@ -3317,7 +3319,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_get_apc_reply,
|
||||
(dump_func)dump_close_handle_reply,
|
||||
(dump_func)dump_set_handle_info_reply,
|
||||
(dump_func)dump_set_handle_cached_fd_reply,
|
||||
(dump_func)dump_dup_handle_reply,
|
||||
(dump_func)dump_open_process_reply,
|
||||
(dump_func)dump_open_thread_reply,
|
||||
|
@ -3334,6 +3335,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_create_file_reply,
|
||||
(dump_func)dump_alloc_file_handle_reply,
|
||||
(dump_func)dump_get_handle_fd_reply,
|
||||
(dump_func)dump_set_handle_fd_reply,
|
||||
(dump_func)dump_flush_file_reply,
|
||||
(dump_func)dump_lock_file_reply,
|
||||
(dump_func)0,
|
||||
|
@ -3525,7 +3527,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"get_apc",
|
||||
"close_handle",
|
||||
"set_handle_info",
|
||||
"set_handle_cached_fd",
|
||||
"dup_handle",
|
||||
"open_process",
|
||||
"open_thread",
|
||||
|
@ -3542,6 +3543,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"create_file",
|
||||
"alloc_file_handle",
|
||||
"get_handle_fd",
|
||||
"set_handle_fd",
|
||||
"flush_file",
|
||||
"lock_file",
|
||||
"unlock_file",
|
||||
|
|
Loading…
Reference in New Issue