1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-25 09:13:06 +00:00

(trunk, libt) #4147 'bad file descriptor': in cached_file_open(), ensure the file is always opened with writable permissions if we need to call ftruncate() to resize it. Large credit to karamanolev for tracking this down with strace.

This commit is contained in:
Jordan Lee 2013-07-27 16:18:12 +00:00
parent f217dc2a60
commit 6897197729

View file

@ -335,7 +335,8 @@ cached_file_open (struct tr_cached_file * o,
{
int flags;
struct stat sb;
bool alreadyExisted;
bool already_existed;
bool resize_needed;
/* create subfolders, if any */
if (writable)
@ -351,12 +352,16 @@ cached_file_open (struct tr_cached_file * o,
tr_free (dir);
}
alreadyExisted = !stat (filename, &sb) && S_ISREG (sb.st_mode);
already_existed = !stat (filename, &sb) && S_ISREG (sb.st_mode);
if (writable && !alreadyExisted && (allocation == TR_PREALLOCATE_FULL))
if (writable && !already_existed && (allocation == TR_PREALLOCATE_FULL))
if (preallocate_file_full (filename, file_size))
tr_logAddDebug ("Preallocated file \"%s\"", filename);
/* we can't resize the file w/o write permissions */
resize_needed = already_existed && (file_size < (uint64_t)sb.st_size);
writable |= resize_needed;
/* open the file */
flags = writable ? (O_RDWR | O_CREAT) : O_RDONLY;
flags |= O_LARGEFILE | O_BINARY | O_SEQUENTIAL;
@ -375,17 +380,14 @@ cached_file_open (struct tr_cached_file * o,
* http://trac.transmissionbt.com/ticket/2228
* https://bugs.launchpad.net/ubuntu/+source/transmission/+bug/318249
*/
if (alreadyExisted && (file_size < (uint64_t)sb.st_size))
if (resize_needed && (ftruncate (o->fd, file_size) == -1))
{
if (ftruncate (o->fd, file_size) == -1)
{
const int err = errno;
tr_logAddError (_("Couldn't truncate \"%1$s\": %2$s"), filename, tr_strerror (err));
return err;
}
const int err = errno;
tr_logAddError (_("Couldn't truncate \"%1$s\": %2$s"), filename, tr_strerror (err));
return err;
}
if (writable && !alreadyExisted && (allocation == TR_PREALLOCATE_SPARSE))
if (writable && !already_existed && (allocation == TR_PREALLOCATE_SPARSE))
preallocate_file_sparse (o->fd, file_size);
/* Many (most?) clients request blocks in ascending order,