SetEndOfFile fix

lawson_whitney at juno.com lawson_whitney at juno.com
Sun Jan 27 15:30:53 CST 2002


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 at juno.com>
	Rein Klazes <rklazes at xs4all.nl>
	Guy Albertelli <galberte at 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)

-------------- next part --------------
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 );


More information about the wine-patches mailing list