----- Original Message ----- From: "Rein Klazes" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Sent: Sunday, January 20, 2002 2:13 PM Subject: SetEndOfFile fix
> hi, > > This fixes office 97 MSword error (disk full or write protected) when > saving files on a vfat partition. MSword calls SetEndOfFile() which > uses ftruncate() that, in Linux, cannot grow files in this filesystem. > > BTW. A google search shows that the ftruncate problem has been > mentioned at least 3 times on c.e.m.w. in the last 6 months Since > nobody entered a fix, I could be overlooking something... This was a great catch. It was the reason Scandisk complained about OutlookExpress's files (see my message from 1/11/2001). However your fix still fails on my outdated kernel (2.2.12-20). The attached version seems to work better on this kernel. Guy
Index: server/file.c =================================================================== RCS file: /home/wine/wine/server/file.c,v retrieving revision 1.53 diff -u -r1.53 file.c --- server/file.c 2002/01/09 20:30:52 1.53 +++ server/file.c 2002/01/26 03:38:49 @@ -456,6 +456,37 @@ 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. If this is the case do + * a write to grow the file to the desired length. + */ +static int _ftruncate ( int fd, off_t length) +{ + struct stat st; + int ret, ret_errno; + char buf[1]={'\0'}; + off_t oldoff; + + ret_errno = errno; + if( fstat( fd, &st ) == -1) return -1; + if( st.st_size == length ) return 0; + errno = ret_errno; + + /* ftruncate() shouldn't fail when requested to shrink the file */ + if( st.st_size > length ) { + ret = ftruncate( fd, length); + return ret; + } + + if( (oldoff = lseek( fd, 0, SEEK_CUR)) == -1) return -1; + if( lseek( fd, length - 1, SEEK_SET) == -1) return -1; + /* write one byte, filepointer is back at the orig. position. */ + if( write( fd, &buf, 1) == -1) return -1; + if( lseek( fd, oldoff, SEEK_SET) == -1) return -1; + return 0; +} + static int truncate_file( handle_t handle ) { struct file *file; @@ -464,8 +495,9 @@ 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)) { + fprintf( stderr, "ftruncate failed\n"); file_set_error(); release_object( file ); return 0;