Added support for mappings with no associated file.

This commit is contained in:
Alexandre Julliard 1999-02-28 10:13:59 +00:00
parent 875d112dd7
commit cb28bdc2c8
4 changed files with 137 additions and 56 deletions

View File

@ -153,6 +153,8 @@ extern struct file *get_file_obj( struct process *process, int handle,
extern int file_get_mmap_fd( struct file *file ); extern int file_get_mmap_fd( struct file *file );
extern int set_file_pointer( int handle, int *low, int *high, int whence ); extern int set_file_pointer( int handle, int *low, int *high, int whence );
extern int truncate_file( int handle ); extern int truncate_file( int handle );
extern int grow_file( struct file *file, int size_high, int size_low );
extern struct file *create_temp_file( int access );
extern int set_file_time( int handle, time_t access_time, time_t write_time ); extern int set_file_time( int handle, time_t access_time, time_t write_time );
extern int file_lock( struct file *file, int offset_high, int offset_low, extern int file_lock( struct file *file, int offset_high, int offset_low,
int count_high, int count_low ); int count_high, int count_low );

View File

@ -1109,37 +1109,8 @@ HANDLE WINAPI CreateFileMappingA(
/* Compute the size and extend the file if necessary */ /* Compute the size and extend the file if necessary */
if (hFile == INVALID_HANDLE_VALUE)
{
if (!size_high && !size_low)
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (name)
{
CHAR buf[260];
GetTempPathA(260,buf);
GetTempFileNameA(buf,"wine",0,buf);
hFile = CreateFileA(
buf,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,/* so we can reuse the tmpfn */
NULL,
OPEN_ALWAYS,
0,
0
);
/* FIXME: bad hack to avoid lots of leftover tempfiles */
DeleteFileA(buf);
if (hFile == INVALID_HANDLE_VALUE)
FIXME(virtual,"could not create temp. file for anon shared mapping: reason was 0x%08lx\n",GetLastError());
}
}
if (hFile != INVALID_HANDLE_VALUE) /* We have a file */ if (hFile != INVALID_HANDLE_VALUE) /* We have a file */
{ {
BY_HANDLE_FILE_INFORMATION info;
DWORD access = GENERIC_READ; DWORD access = GENERIC_READ;
if (((protect & 0xff) == PAGE_READWRITE) || if (((protect & 0xff) == PAGE_READWRITE) ||
@ -1150,21 +1121,6 @@ HANDLE WINAPI CreateFileMappingA(
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile, if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
K32OBJ_FILE, access )) == -1) goto error; K32OBJ_FILE, access )) == -1) goto error;
if (!GetFileInformationByHandle( hFile, &info )) goto error;
if (!size_high && !size_low)
{
size_high = info.nFileSizeHigh;
size_low = info.nFileSizeLow;
}
else if ((size_high > info.nFileSizeHigh) ||
((size_high == info.nFileSizeHigh) &&
(size_low > info.nFileSizeLow)))
{
/* We have to grow the file */
if (SetFilePointer( hFile, size_low, &size_high,
FILE_BEGIN ) == 0xffffffff) goto error;
if (!SetEndOfFile( hFile )) goto error;
}
} }
else req.handle = -1; else req.handle = -1;
@ -1173,6 +1129,7 @@ HANDLE WINAPI CreateFileMappingA(
req.size_high = size_high; req.size_high = size_high;
req.size_low = ROUND_SIZE( 0, size_low ); req.size_low = ROUND_SIZE( 0, size_low );
req.protect = vprot; req.protect = vprot;
req.inherit = inherit;
CLIENT_SendRequest( REQ_CREATE_MAPPING, -1, 2, CLIENT_SendRequest( REQ_CREATE_MAPPING, -1, 2,
&req, sizeof(req), &req, sizeof(req),
name, name ? strlen(name) + 1 : 0 ); name, name ? strlen(name) + 1 : 0 );

View File

@ -199,6 +199,45 @@ struct object *create_file( int fd, const char *name, unsigned int access,
return &file->obj; return &file->obj;
} }
/* Create a temp file for anonymous mappings */
struct file *create_temp_file( int access )
{
struct file *file;
char *name;
int fd;
do
{
if (!(name = tmpnam(NULL)))
{
SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
return NULL;
}
fd = open( name, O_CREAT | O_EXCL | O_RDWR, 0600 );
} while ((fd == -1) && (errno == EEXIST));
if (fd == -1)
{
file_set_error();
return NULL;
}
unlink( name );
if (!(file = mem_alloc( sizeof(*file) )))
{
close( fd );
return NULL;
}
init_object( &file->obj, &file_ops, NULL );
file->name = NULL;
file->next = NULL;
file->fd = fd;
file->access = access;
file->flags = 0;
file->sharing = 0;
CLEAR_ERROR();
return file;
}
static void file_dump( struct object *obj, int verbose ) static void file_dump( struct object *obj, int verbose )
{ {
struct file *file = (struct file *)obj; struct file *file = (struct file *)obj;
@ -406,6 +445,27 @@ int truncate_file( int handle )
} }
/* try to grow the file to the specified size */
int grow_file( struct file *file, int size_high, int size_low )
{
struct stat st;
if (size_high)
{
SET_ERROR( ERROR_INVALID_PARAMETER );
return 0;
}
if (fstat( file->fd, &st ) == -1)
{
file_set_error();
return 0;
}
if (st.st_size >= size_low) return 1; /* already large enough */
if (ftruncate( file->fd, size_low ) != -1) return 1;
file_set_error();
return 0;
}
int set_file_time( int handle, time_t access_time, time_t write_time ) int set_file_time( int handle, time_t access_time, time_t write_time )
{ {
struct file *file; struct file *file;

View File

@ -9,6 +9,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include "config.h"
#include "winerror.h" #include "winerror.h"
#include "winnt.h" #include "winnt.h"
#include "server/process.h" #include "server/process.h"
@ -40,10 +41,51 @@ static const struct object_ops mapping_ops =
mapping_destroy mapping_destroy
}; };
#ifdef __i386__
/* These are always the same on an i386, and it will be faster this way */
# define page_mask 0xfff
# define page_shift 12
# define init_page_size() /* nothing */
#else /* __i386__ */
static int page_shift, page_mask;
static void init_page_size(void)
{
int page_size;
# ifdef HAVE_GETPAGESIZE
page_size = getpagesize();
# else
# ifdef __svr4__
page_size = sysconf(_SC_PAGESIZE);
# else
# error Cannot get the page size on this platform
# endif
# endif
page_mask = page_size - 1;
/* Make sure we have a power of 2 */
assert( !(page_size & page_mask) );
page_shift = 0;
while ((1 << page_shift) != page_size) page_shift++;
}
#endif /* __i386__ */
#define ROUND_ADDR(addr) \
((int)(addr) & ~page_mask)
#define ROUND_SIZE(addr,size) \
(((int)(size) + ((int)(addr) & page_mask) + page_mask) & ~page_mask)
struct object *create_mapping( int size_high, int size_low, int protect, struct object *create_mapping( int size_high, int size_low, int protect,
int handle, const char *name ) int handle, const char *name )
{ {
struct mapping *mapping; struct mapping *mapping;
int access = 0;
if (!page_mask) init_page_size();
if (!(mapping = (struct mapping *)create_named_object( name, &mapping_ops, if (!(mapping = (struct mapping *)create_named_object( name, &mapping_ops,
sizeof(*mapping) ))) sizeof(*mapping) )))
@ -51,23 +93,43 @@ struct object *create_mapping( int size_high, int size_low, int protect,
if (GET_ERROR() == ERROR_ALREADY_EXISTS) if (GET_ERROR() == ERROR_ALREADY_EXISTS)
return &mapping->obj; /* Nothing else to do */ return &mapping->obj; /* Nothing else to do */
if (protect & VPROT_READ) access |= GENERIC_READ;
if (protect & VPROT_WRITE) access |= GENERIC_WRITE;
size_low = ROUND_SIZE( 0, size_low );
if (handle != -1)
{
if (!(mapping->file = get_file_obj( current->process, handle, access ))) goto error;
if (!size_high && !size_low)
{
struct get_file_info_reply reply;
struct object *obj = (struct object *)mapping->file;
obj->ops->get_file_info( obj, &reply );
size_high = reply.size_high;
size_low = ROUND_SIZE( 0, reply.size_low );
}
else if (!grow_file( mapping->file, size_high, size_low )) goto error;
}
else /* Anonymous mapping (no associated file) */
{
if (!size_high && !size_low)
{
SET_ERROR( ERROR_INVALID_PARAMETER );
mapping->file = NULL;
goto error;
}
if (!(mapping->file = create_temp_file( access ))) goto error;
if (!grow_file( mapping->file, size_high, size_low )) goto error;
}
mapping->size_high = size_high; mapping->size_high = size_high;
mapping->size_low = size_low; mapping->size_low = size_low;
mapping->protect = protect; mapping->protect = protect;
if (handle != -1) return &mapping->obj;
{
int access = 0; error:
if (protect & VPROT_READ) access |= GENERIC_READ;
if (protect & VPROT_WRITE) access |= GENERIC_WRITE;
if (!(mapping->file = get_file_obj( current->process, handle, access )))
{
release_object( mapping ); release_object( mapping );
return NULL; return NULL;
} }
}
else mapping->file = NULL;
return &mapping->obj;
}
int open_mapping( unsigned int access, int inherit, const char *name ) int open_mapping( unsigned int access, int inherit, const char *name )
{ {