On Sun, 27 Jan 2002, Rein Klazes wrote: > You still need ftruncate in case the file has to shrink. To do that > without ftruncate takes a lot more work then an lseek and a write. > > Rein. > Right. I meant sort of like this. Unfortunately I haven't an app that does this, to be sure I have it right. Changelog server : file.c Lawson Whitney <lawson_whitney@juno.com> Rein Klazes <rklazes@xs4all.nl> Guy Albertelli <galberte@neo.lrun.com> Do not rely on ftruncate to grow a file. It may refuse or fail to do so. (eg with vfat filesystem under Linux)
diff -urN was/server/file.c is/server/file.c --- was/server/file.c Tue Jan 22 20:57:40 2002 +++ is/server/file.c Sun Jan 27 15:52:51 2002 @@ -456,6 +456,28 @@ return 1; } +/* wrapper around ftruncate: + * ftruncate may fail to grow the size of a file with some OS and filesystem + * combinations. Linux and vfat/fat is one example. To work around this do + * a write to grow the file to the desired length. + */ +static int _ftruncate ( int fd, off_t length) +{ + struct stat st; + int ret_errno; + char buf[1]={'\0'}; + ret_errno = errno; + if( fstat( fd, &st ) == -1) return -1; + errno = ret_errno; + /* ftruncate() shouldn't fail when requested to shrink the file */ + if( st.st_size >= length ) return ftruncate( fd, length); + /* file pointer is at the requested size */ + if( lseek( fd, -1, SEEK_CUR) == -1) return -1; + /* write one byte, filepointer is back at the orig. position. */ + if( write( fd, &buf, 1) == -1) return -1; + return 0; +} + static int truncate_file( handle_t handle ) { struct file *file; @@ -464,7 +486,7 @@ 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)) + (_ftruncate( file->obj.fd, result ) == -1)) { file_set_error(); release_object( file );