mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-15 11:02:51 +00:00
Work around ftruncate implementations that don't support extending
files.
This commit is contained in:
parent
5d93b6ede9
commit
86e5efb6b3
|
@ -456,29 +456,46 @@ static int set_file_pointer( handle_t handle, unsigned int *low, int *high, int
|
||||||
return 1;
|
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;
|
static const char zero;
|
||||||
off_t result;
|
|
||||||
|
|
||||||
if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
|
/* extend the file one byte beyond the requested size and then truncate it */
|
||||||
return 0;
|
/* this should work around ftruncate implementations that can't extend files */
|
||||||
if (((result = lseek( file->obj.fd, 0, SEEK_CUR )) == -1) ||
|
if ((lseek( file->obj.fd, size, SEEK_SET ) != -1) &&
|
||||||
(ftruncate( file->obj.fd, result ) == -1))
|
(write( file->obj.fd, &zero, 1 ) != -1))
|
||||||
{
|
{
|
||||||
file_set_error();
|
ftruncate( file->obj.fd, size );
|
||||||
release_object( file );
|
return 1;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
release_object( file );
|
file_set_error();
|
||||||
return 1;
|
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 */
|
/* 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, int size_high, int size_low )
|
||||||
{
|
{
|
||||||
|
int ret = 0;
|
||||||
struct stat st;
|
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)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
if (st.st_size >= size) return 1; /* already large enough */
|
if (st.st_size >= size) return 1; /* already large enough */
|
||||||
if (ftruncate( file->obj.fd, size ) != -1) return 1;
|
old_pos = lseek( file->obj.fd, 0, SEEK_CUR ); /* save old pos */
|
||||||
file_set_error();
|
ret = extend_file( file, size );
|
||||||
return 0;
|
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 )
|
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 */
|
/* truncate (or extend) a file */
|
||||||
DECL_HANDLER(truncate_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 */
|
/* flush a file buffers */
|
||||||
|
|
Loading…
Reference in a new issue