Cleaned up handling of 64-bit file sizes.
This commit is contained in:
parent
95fe6abcb7
commit
a4334a6b95
|
@ -379,11 +379,17 @@ int get_file_unix_fd( struct file *file )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* extend a file beyond the current end of file */
|
/* extend a file beyond the current end of file */
|
||||||
static int extend_file( struct file *file, off_t size )
|
static int extend_file( struct file *file, file_pos_t new_size )
|
||||||
{
|
{
|
||||||
static const char zero;
|
static const char zero;
|
||||||
int unix_fd = get_file_unix_fd( file );
|
int unix_fd = get_file_unix_fd( file );
|
||||||
|
off_t size = new_size;
|
||||||
|
|
||||||
|
if (sizeof(new_size) > sizeof(size) && size != new_size)
|
||||||
|
{
|
||||||
|
set_error( STATUS_INVALID_PARAMETER );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/* extend the file one byte beyond the requested size and then truncate it */
|
/* extend the file one byte beyond the requested size and then truncate it */
|
||||||
/* this should work around ftruncate implementations that can't extend files */
|
/* this should work around ftruncate implementations that can't extend files */
|
||||||
if (pwrite( unix_fd, &zero, 1, size ) != -1)
|
if (pwrite( unix_fd, &zero, 1, size ) != -1)
|
||||||
|
@ -396,11 +402,10 @@ static int extend_file( struct file *file, off_t size )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try to grow the file to the specified size */
|
/* try to grow the file to the specified size */
|
||||||
int grow_file( struct file *file, int size_high, int size_low )
|
int grow_file( struct file *file, file_pos_t size )
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int unix_fd = get_file_unix_fd( file );
|
int unix_fd = get_file_unix_fd( file );
|
||||||
off_t size = size_low + (((off_t)size_high)<<32);
|
|
||||||
|
|
||||||
if (fstat( unix_fd, &st ) == -1)
|
if (fstat( unix_fd, &st ) == -1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,7 +96,7 @@ extern struct file *get_file_obj( struct process *process, obj_handle_t handle,
|
||||||
unsigned int access );
|
unsigned int access );
|
||||||
extern int get_file_unix_fd( struct file *file );
|
extern int get_file_unix_fd( struct file *file );
|
||||||
extern int is_same_file( struct file *file1, struct file *file2 );
|
extern int is_same_file( struct file *file1, struct file *file2 );
|
||||||
extern int grow_file( struct file *file, int size_high, int size_low );
|
extern int grow_file( struct file *file, file_pos_t size );
|
||||||
extern struct file *create_temp_file( int access );
|
extern struct file *create_temp_file( int access );
|
||||||
extern void file_set_error(void);
|
extern void file_set_error(void);
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,7 @@
|
||||||
struct mapping
|
struct mapping
|
||||||
{
|
{
|
||||||
struct object obj; /* object header */
|
struct object obj; /* object header */
|
||||||
int size_high; /* mapping size */
|
file_pos_t size; /* mapping size */
|
||||||
int size_low; /* mapping size */
|
|
||||||
int protect; /* protection flags */
|
int protect; /* protection flags */
|
||||||
struct file *file; /* file mapped */
|
struct file *file; /* file mapped */
|
||||||
int header_size; /* size of headers (for PE image mapping) */
|
int header_size; /* size of headers (for PE image mapping) */
|
||||||
|
@ -100,13 +99,10 @@ static void init_page_size(void)
|
||||||
}
|
}
|
||||||
#endif /* __i386__ */
|
#endif /* __i386__ */
|
||||||
|
|
||||||
#define ROUND_ADDR(addr) \
|
|
||||||
((int)(addr) & ~page_mask)
|
|
||||||
|
|
||||||
#define ROUND_SIZE_MASK(addr,size,mask) \
|
#define ROUND_SIZE_MASK(addr,size,mask) \
|
||||||
(((int)(size) + ((int)(addr) & (mask)) + (mask)) & ~(mask))
|
(((int)(size) + ((int)(addr) & (mask)) + (mask)) & ~(mask))
|
||||||
|
|
||||||
#define ROUND_SIZE(addr,size) ROUND_SIZE_MASK( addr, size, page_mask )
|
#define ROUND_SIZE(size) (((size) + page_mask) & ~page_mask)
|
||||||
|
|
||||||
|
|
||||||
/* find the shared PE mapping for a given mapping */
|
/* find the shared PE mapping for a given mapping */
|
||||||
|
@ -122,9 +118,9 @@ static struct file *get_shared_file( struct mapping *mapping )
|
||||||
|
|
||||||
/* allocate and fill the temp file for a shared PE image mapping */
|
/* allocate and fill the temp file for a shared PE image mapping */
|
||||||
static int build_shared_mapping( struct mapping *mapping, int fd,
|
static int build_shared_mapping( struct mapping *mapping, int fd,
|
||||||
IMAGE_SECTION_HEADER *sec, int nb_sec )
|
IMAGE_SECTION_HEADER *sec, unsigned int nb_sec )
|
||||||
{
|
{
|
||||||
int i, max_size, total_size;
|
unsigned int i, max_size, total_size;
|
||||||
off_t shared_pos, read_pos, write_pos;
|
off_t shared_pos, read_pos, write_pos;
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
int shared_fd;
|
int shared_fd;
|
||||||
|
@ -138,7 +134,7 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
|
||||||
if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) &&
|
if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) &&
|
||||||
(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE))
|
(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE))
|
||||||
{
|
{
|
||||||
int size = ROUND_SIZE( 0, sec[i].Misc.VirtualSize );
|
unsigned int size = ROUND_SIZE( sec[i].Misc.VirtualSize );
|
||||||
if (size > max_size) max_size = size;
|
if (size > max_size) max_size = size;
|
||||||
total_size += size;
|
total_size += size;
|
||||||
}
|
}
|
||||||
|
@ -150,7 +146,7 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
|
||||||
/* create a temp file for the mapping */
|
/* create a temp file for the mapping */
|
||||||
|
|
||||||
if (!(mapping->shared_file = create_temp_file( GENERIC_READ|GENERIC_WRITE ))) return 0;
|
if (!(mapping->shared_file = create_temp_file( GENERIC_READ|GENERIC_WRITE ))) return 0;
|
||||||
if (!grow_file( mapping->shared_file, 0, total_size )) goto error;
|
if (!grow_file( mapping->shared_file, total_size )) goto error;
|
||||||
if ((shared_fd = get_file_unix_fd( mapping->shared_file )) == -1) goto error;
|
if ((shared_fd = get_file_unix_fd( mapping->shared_file )) == -1) goto error;
|
||||||
|
|
||||||
if (!(buffer = malloc( max_size ))) goto error;
|
if (!(buffer = malloc( max_size ))) goto error;
|
||||||
|
@ -163,7 +159,7 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
|
||||||
if (!(sec[i].Characteristics & IMAGE_SCN_MEM_SHARED)) continue;
|
if (!(sec[i].Characteristics & IMAGE_SCN_MEM_SHARED)) continue;
|
||||||
if (!(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) continue;
|
if (!(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) continue;
|
||||||
write_pos = shared_pos;
|
write_pos = shared_pos;
|
||||||
shared_pos += ROUND_SIZE( 0, sec[i].Misc.VirtualSize );
|
shared_pos += ROUND_SIZE( sec[i].Misc.VirtualSize );
|
||||||
if ((sec[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) &&
|
if ((sec[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) &&
|
||||||
!(sec[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)) continue;
|
!(sec[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)) continue;
|
||||||
if (!sec[i].PointerToRawData || !sec[i].SizeOfRawData) continue;
|
if (!sec[i].PointerToRawData || !sec[i].SizeOfRawData) continue;
|
||||||
|
@ -235,15 +231,14 @@ static int get_image_params( struct mapping *mapping )
|
||||||
shared_first = mapping;
|
shared_first = mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping->size_low = ROUND_SIZE( 0, nt.OptionalHeader.SizeOfImage );
|
mapping->size = ROUND_SIZE( nt.OptionalHeader.SizeOfImage );
|
||||||
mapping->size_high = 0;
|
|
||||||
mapping->base = (void *)nt.OptionalHeader.ImageBase;
|
mapping->base = (void *)nt.OptionalHeader.ImageBase;
|
||||||
mapping->header_size = ROUND_SIZE_MASK( mapping->base, nt.OptionalHeader.SizeOfHeaders,
|
mapping->header_size = ROUND_SIZE_MASK( mapping->base, nt.OptionalHeader.SizeOfHeaders,
|
||||||
nt.OptionalHeader.SectionAlignment - 1 );
|
nt.OptionalHeader.SectionAlignment - 1 );
|
||||||
mapping->protect = VPROT_IMAGE;
|
mapping->protect = VPROT_IMAGE;
|
||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
if (mapping->header_size > mapping->size_low) goto error;
|
if (mapping->header_size > mapping->size) goto error;
|
||||||
|
|
||||||
free( sec );
|
free( sec );
|
||||||
release_object( fd );
|
release_object( fd );
|
||||||
|
@ -257,19 +252,18 @@ static int get_image_params( struct mapping *mapping )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the size of the unix file associated with the mapping */
|
/* get the size of the unix file associated with the mapping */
|
||||||
inline static int get_file_size( struct file *file, int *size_high, int *size_low )
|
inline static int get_file_size( struct file *file, file_pos_t *size )
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int unix_fd = get_file_unix_fd( file );
|
int unix_fd = get_file_unix_fd( file );
|
||||||
|
|
||||||
if (fstat( unix_fd, &st ) == -1) return 0;
|
if (fstat( unix_fd, &st ) == -1) return 0;
|
||||||
*size_high = st.st_size >> 32;
|
*size = st.st_size;
|
||||||
*size_low = st.st_size & 0xffffffff;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct object *create_mapping( int size_high, int size_low, int protect,
|
static struct object *create_mapping( file_pos_t size, int protect, obj_handle_t handle,
|
||||||
obj_handle_t handle, const WCHAR *name, size_t len )
|
const WCHAR *name, size_t len )
|
||||||
{
|
{
|
||||||
struct mapping *mapping;
|
struct mapping *mapping;
|
||||||
int access = 0;
|
int access = 0;
|
||||||
|
@ -297,10 +291,10 @@ static struct object *create_mapping( int size_high, int size_low, int protect,
|
||||||
if (!get_image_params( mapping )) goto error;
|
if (!get_image_params( mapping )) goto error;
|
||||||
return &mapping->obj;
|
return &mapping->obj;
|
||||||
}
|
}
|
||||||
if (!size_high && !size_low)
|
if (!size)
|
||||||
{
|
{
|
||||||
if (!get_file_size( mapping->file, &size_high, &size_low )) goto error;
|
if (!get_file_size( mapping->file, &size )) goto error;
|
||||||
if (!size_high && !size_low)
|
if (!size)
|
||||||
{
|
{
|
||||||
set_error( STATUS_FILE_INVALID );
|
set_error( STATUS_FILE_INVALID );
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -308,22 +302,21 @@ static struct object *create_mapping( int size_high, int size_low, int protect,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!grow_file( mapping->file, size_high, size_low )) goto error;
|
if (!grow_file( mapping->file, size )) goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* Anonymous mapping (no associated file) */
|
else /* Anonymous mapping (no associated file) */
|
||||||
{
|
{
|
||||||
if ((!size_high && !size_low) || (protect & VPROT_IMAGE))
|
if (!size || (protect & VPROT_IMAGE))
|
||||||
{
|
{
|
||||||
set_error( STATUS_INVALID_PARAMETER );
|
set_error( STATUS_INVALID_PARAMETER );
|
||||||
mapping->file = NULL;
|
mapping->file = NULL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!(mapping->file = create_temp_file( access ))) goto error;
|
if (!(mapping->file = create_temp_file( access ))) goto error;
|
||||||
if (!grow_file( mapping->file, size_high, size_low )) goto error;
|
if (!grow_file( mapping->file, size )) goto error;
|
||||||
}
|
}
|
||||||
mapping->size_high = size_high;
|
mapping->size = (size + page_mask) & ~((file_pos_t)page_mask);
|
||||||
mapping->size_low = ROUND_SIZE( 0, size_low );
|
|
||||||
mapping->protect = protect;
|
mapping->protect = protect;
|
||||||
return &mapping->obj;
|
return &mapping->obj;
|
||||||
|
|
||||||
|
@ -338,8 +331,9 @@ static void mapping_dump( struct object *obj, int verbose )
|
||||||
assert( obj->ops == &mapping_ops );
|
assert( obj->ops == &mapping_ops );
|
||||||
fprintf( stderr, "Mapping size=%08x%08x prot=%08x file=%p header_size=%08x base=%p "
|
fprintf( stderr, "Mapping size=%08x%08x prot=%08x file=%p header_size=%08x base=%p "
|
||||||
"shared_file=%p shared_size=%08x ",
|
"shared_file=%p shared_size=%08x ",
|
||||||
mapping->size_high, mapping->size_low, mapping->protect, mapping->file,
|
(unsigned int)(mapping->size >> 32), (unsigned int)mapping->size,
|
||||||
mapping->header_size, mapping->base, mapping->shared_file, mapping->shared_size );
|
mapping->protect, mapping->file, mapping->header_size,
|
||||||
|
mapping->base, mapping->shared_file, mapping->shared_size );
|
||||||
dump_object_name( &mapping->obj );
|
dump_object_name( &mapping->obj );
|
||||||
fputc( '\n', stderr );
|
fputc( '\n', stderr );
|
||||||
}
|
}
|
||||||
|
@ -374,10 +368,10 @@ int get_page_size(void)
|
||||||
DECL_HANDLER(create_mapping)
|
DECL_HANDLER(create_mapping)
|
||||||
{
|
{
|
||||||
struct object *obj;
|
struct object *obj;
|
||||||
|
file_pos_t size = ((file_pos_t)req->size_high << 32) | req->size_low;
|
||||||
|
|
||||||
reply->handle = 0;
|
reply->handle = 0;
|
||||||
if ((obj = create_mapping( req->size_high, req->size_low,
|
if ((obj = create_mapping( size, req->protect, req->file_handle,
|
||||||
req->protect, req->file_handle,
|
|
||||||
get_req_data(), get_req_data_size() )))
|
get_req_data(), get_req_data_size() )))
|
||||||
{
|
{
|
||||||
reply->handle = alloc_handle( current->process, obj, req->access, req->inherit );
|
reply->handle = alloc_handle( current->process, obj, req->access, req->inherit );
|
||||||
|
@ -400,8 +394,8 @@ DECL_HANDLER(get_mapping_info)
|
||||||
if ((mapping = (struct mapping *)get_handle_obj( current->process, req->handle,
|
if ((mapping = (struct mapping *)get_handle_obj( current->process, req->handle,
|
||||||
0, &mapping_ops )))
|
0, &mapping_ops )))
|
||||||
{
|
{
|
||||||
reply->size_high = mapping->size_high;
|
reply->size_high = (unsigned int)(mapping->size >> 32);
|
||||||
reply->size_low = mapping->size_low;
|
reply->size_low = (unsigned int)mapping->size;
|
||||||
reply->protect = mapping->protect;
|
reply->protect = mapping->protect;
|
||||||
reply->header_size = mapping->header_size;
|
reply->header_size = mapping->header_size;
|
||||||
reply->base = mapping->base;
|
reply->base = mapping->base;
|
||||||
|
|
Loading…
Reference in New Issue