Skip to content
Snippets Groups Projects
Commit 86e5efb6 authored by Alexandre Julliard's avatar Alexandre Julliard
Browse files

Work around ftruncate implementations that don't support extending

files.
parent 5d93b6ed
No related branches found
No related tags found
No related merge requests found
......@@ -456,29 +456,46 @@ static int set_file_pointer( handle_t handle, unsigned int *low, int *high, int
return 1;
}
static int truncate_file( handle_t handle )
/* extend a file beyond the current end of file */
static int extend_file( struct file *file, off_t size )
{
struct file *file;
off_t result;
static const char zero;
if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
return 0;
if (((result = lseek( file->obj.fd, 0, SEEK_CUR )) == -1) ||
(ftruncate( file->obj.fd, result ) == -1))
/* 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))
{
file_set_error();
release_object( file );
return 0;
ftruncate( file->obj.fd, size );
return 1;
}
release_object( file );
return 1;
file_set_error();
return 0;
}
/* truncate file at current position */
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 );
if (eof < pos) ret = extend_file( file, pos );
else
{
if (ftruncate( file->obj.fd, pos ) != -1) ret = 1;
else file_set_error();
}
lseek( file->obj.fd, pos, SEEK_SET ); /* restore file pos */
return ret;
}
/* try to grow the file to the specified size */
int grow_file( struct file *file, int size_high, int size_low )
{
int ret = 0;
struct stat st;
off_t size = size_low + (((off_t)size_high)<<32);
off_t old_pos, size = size_low + (((off_t)size_high)<<32);
if (fstat( file->obj.fd, &st ) == -1)
{
......@@ -486,9 +503,10 @@ int grow_file( struct file *file, int size_high, int size_low )
return 0;
}
if (st.st_size >= size) return 1; /* already large enough */
if (ftruncate( file->obj.fd, size ) != -1) return 1;
file_set_error();
return 0;
old_pos = lseek( file->obj.fd, 0, SEEK_CUR ); /* save old pos */
ret = extend_file( file, size );
lseek( file->obj.fd, old_pos, SEEK_SET ); /* restore file pos */
return ret;
}
static int set_file_time( handle_t handle, time_t access_time, time_t write_time )
......@@ -604,7 +622,13 @@ DECL_HANDLER(set_file_pointer)
/* truncate (or extend) a file */
DECL_HANDLER(truncate_file)
{
truncate_file( req->handle );
struct file *file;
if ((file = get_file_obj( current->process, req->handle, GENERIC_WRITE )))
{
truncate_file( file );
release_object( file );
}
}
/* flush a file buffers */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment