Opened 14 years ago

Closed 14 years ago

#329 closed Bug (fixed)

Files greater than 4 GB are truncated when being written

Reported by: Eric Owned by: somebody
Priority: Normal Milestone: None Set
Component: Transmission Version: 0.82+
Severity: Major Keywords:


In libtransmission/inout.c the ensureMinimumFileSize function casts sb.st_size to a size_t which is a 4-byte value. But sb.st_size is of type off_t, an 8-byte value.

The result of this is that whenever the file size is greater than 4 GB and a piece is being written to the file somewhere before the 4 GB point, the file is truncated at the end of the data block being written.

This effectively prevents Transmission from downloading files greater than 4 GB... unless by chance the pieces are all downloaded sequentially.

Change History (3)

comment:1 Changed 14 years ago by erdgeist

The line in question checks for file size already being larger than minSize. That check should fail if the cast truncates file size and thus the file will always be ftruncated to minSize which should not produce the effect described.

Even _IF_ ftruncate was not called, the following would happen: ensureMinimumFileSize is only called from readOrWritePiece, which in turn calls readOrWriteBytes which lseek()s to the write location and write()s the piece there. The lseek()/write() combination also enlarges the file. So that incorrect cast can not lead to the 4GB-issue.

However, here is a tiny patch:

--- inout.c	(revision 2978)
+++ inout.c	(working copy)
@@ -125,7 +125,7 @@
         ret = fd;
     else if (fstat (fd, &sb) ) /* how big is the file? */
         ret = tr_ioErrorFromErrno ();
-    else if ((size_t)sb.st_size >= minSize) /* already big enough */
+    else if ((uint64_t)sb.st_size >= minSize) /* already big enough */
         ret = TR_OK;
     else if (!ftruncate( fd, minSize )) /* grow it */
         ret = TR_OK;

comment:2 Changed 14 years ago by erdgeist


The fix incorporated in r2980 (as outlined above) _does_ really fix the issue.

What happend before was: readOrWritePiece would call ensureMinimumFileSize with an offset smaller than file current file size once in a while. If the offset would be <4gb and file size >4gb, then the file would have been truncated to the offset given.

I would plead for ensureMinimumFileSize to be removed completely as it serves no use. All posix conform implemtations would enlarge files when writing to them, anyway. If sparse files would become a problem one day, libtransmission could handle that later on.

comment:3 Changed 14 years ago by livings124

  • Resolution set to fixed
  • Status changed from new to closed

Should be fixed in [2779], [2780], and [2781].

Note: See TracTickets for help on using tickets.