From 6897197729696c040ba3640ad94f86e11e8e0ec9 Mon Sep 17 00:00:00 2001 From: Jordan Lee Date: Sat, 27 Jul 2013 16:18:12 +0000 Subject: [PATCH] (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. --- libtransmission/fdlimit.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/libtransmission/fdlimit.c b/libtransmission/fdlimit.c index 546e988a2..2a1bf4e3d 100644 --- a/libtransmission/fdlimit.c +++ b/libtransmission/fdlimit.c @@ -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, -- 2.40.0