(trunk, libt) #4160 - the slow slog to catch trunk up to mike.dld's 4160 diff continues. This step applies 4160-03b-file.patch, which replaces native file operations with the tr_sys_file_*() portability wrappers added in r14321.

This commit is contained in:
Jordan Lee 2014-07-28 04:13:38 +00:00
parent 2c0276fc23
commit b33a7d4dc1
15 changed files with 229 additions and 607 deletions

View File

@ -9,6 +9,7 @@
#include <assert.h>
#include <stdio.h>
#include <string.h> /* strlen () */
#include <unistd.h> /* sync() */
#include "transmission.h"
@ -36,17 +37,16 @@ static const char * contents2 =
static void
create_text_file (const char * path, const char * contents)
{
FILE * fp;
tr_sys_file_t fd;
char * dir;
dir = tr_sys_path_dirname (path, NULL);
tr_mkdirp (dir, 0700);
tr_free (dir);
tr_sys_path_remove (path, NULL);
fp = fopen (path, "w+");
fprintf (fp, "%s", contents);
fclose (fp);
fd = tr_sys_file_open (path, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE, 0600, NULL);
tr_sys_file_write (fd, contents, strlen (contents), NULL, NULL);
tr_sys_file_close (fd, NULL);
sync ();
}

View File

@ -13,32 +13,14 @@
#include <stdlib.h> /* bsearch (), qsort () */
#include <string.h>
#include <unistd.h> /* close () */
#ifdef _WIN32
#include <w32api.h>
#define WINVER WindowsXP
#include <windows.h>
#define PROT_READ PAGE_READONLY
#define MAP_PRIVATE FILE_MAP_COPY
#endif
#ifndef _WIN32
#include <sys/mman.h>
#endif
#include <fcntl.h>
#include "transmission.h"
#include "blocklist.h"
#include "error.h"
#include "file.h"
#include "log.h"
#include "net.h"
#include "utils.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
/***
**** PRIVATE
@ -53,9 +35,9 @@ struct tr_ipv4_range
struct tr_blocklistFile
{
bool isEnabled;
int fd;
tr_sys_file_t fd;
size_t ruleCount;
size_t byteCount;
uint64_t byteCount;
char * filename;
struct tr_ipv4_range * rules;
};
@ -65,22 +47,23 @@ blocklistClose (tr_blocklistFile * b)
{
if (b->rules != NULL)
{
munmap (b->rules, b->byteCount);
close (b->fd);
tr_sys_file_unmap (b->rules, b->byteCount, NULL);
tr_sys_file_close (b->fd, NULL);
b->rules = NULL;
b->ruleCount = 0;
b->byteCount = 0;
b->fd = -1;
b->fd = TR_BAD_SYS_FILE;
}
}
static void
blocklistLoad (tr_blocklistFile * b)
{
int fd;
size_t byteCount;
tr_sys_file_t fd;
uint64_t byteCount;
tr_sys_path_info info;
char * base;
tr_error * error = NULL;
const char * err_fmt = _("Couldn't read \"%1$s\": %2$s");
blocklistClose (b);
@ -88,22 +71,24 @@ blocklistLoad (tr_blocklistFile * b)
if (!tr_sys_path_get_info (b->filename, 0, &info, NULL))
return;
byteCount = (size_t) info.size;
byteCount = info.size;
if (byteCount == 0)
return;
fd = open (b->filename, O_RDONLY | O_BINARY);
if (fd == -1)
fd = tr_sys_file_open (b->filename, TR_SYS_FILE_READ, 0, &error);
if (fd == TR_BAD_SYS_FILE)
{
tr_logAddError (err_fmt, b->filename, tr_strerror (errno));
tr_logAddError (err_fmt, b->filename, error->message);
tr_error_free (error);
return;
}
b->rules = mmap (NULL, byteCount, PROT_READ, MAP_PRIVATE, fd, 0);
b->rules = tr_sys_file_map_for_reading (fd, 0, byteCount, &error);
if (!b->rules)
{
tr_logAddError (err_fmt, b->filename, tr_strerror (errno));
close (fd);
tr_logAddError (err_fmt, b->filename, error->message);
tr_sys_file_close (fd, NULL);
tr_error_free (error);
return;
}
@ -151,7 +136,7 @@ tr_blocklistFileNew (const char * filename, bool isEnabled)
tr_blocklistFile * b;
b = tr_new0 (tr_blocklistFile, 1);
b->fd = -1;
b->fd = TR_BAD_SYS_FILE;
b->filename = tr_strdup (filename);
b->isEnabled = isEnabled;

View File

@ -7,38 +7,16 @@
* $Id$
*/
#ifdef HAVE_POSIX_FADVISE
#ifdef _XOPEN_SOURCE
#undef _XOPEN_SOURCE
#endif
#define _XOPEN_SOURCE 600
#endif
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <string.h>
#ifdef __APPLE__
#include <fcntl.h>
#endif
#ifdef HAVE_FALLOCATE64
/* FIXME can't find the right #include voodoo to pick up the declaration.. */
extern int fallocate64 (int fd, int mode, uint64_t offset, uint64_t len);
#endif
#ifdef HAVE_XFS_XFS_H
#include <xfs/xfs.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h> /* getrlimit */
#include <sys/resource.h> /* getrlimit */
#include <fcntl.h> /* O_LARGEFILE posix_fadvise */
#include <unistd.h> /* lseek (), write (), ftruncate (), pread (), pwrite (), etc */
#include "transmission.h"
#include "error.h"
#include "fdlimit.h"
#include "file.h"
#include "log.h"
@ -59,21 +37,8 @@
****
***/
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef O_SEQUENTIAL
#define O_SEQUENTIAL 0
#endif
static bool
preallocate_file_sparse (int fd, uint64_t length)
preallocate_file_sparse (tr_sys_file_t fd, uint64_t length)
{
const char zero = '\0';
bool success = 0;
@ -81,15 +46,18 @@ preallocate_file_sparse (int fd, uint64_t length)
if (!length)
success = true;
#ifdef HAVE_FALLOCATE64
if (!success) /* fallocate64 is always preferred, so try it first */
success = !fallocate64 (fd, 0, 0, length);
#endif
if (!success)
success = tr_sys_file_preallocate (fd, length, TR_SYS_FILE_PREALLOC_SPARSE, NULL);
if (!success) /* fallback: the old-style seek-and-write */
success = (lseek (fd, length-1, SEEK_SET) != -1)
&& (write (fd, &zero, 1) != -1)
&& (ftruncate (fd, length) != -1);
{
/* seek requires signed offset, so length should be in mod range */
assert (length < 0x7FFFFFFFFFFFFFFFULL);
success = tr_sys_file_seek (fd, length - 1, TR_SEEK_SET, NULL, NULL) &&
tr_sys_file_write (fd, &zero, 1, NULL, NULL) &&
tr_sys_file_truncate (fd, length, NULL);
}
return success;
}
@ -99,53 +67,10 @@ preallocate_file_full (const char * filename, uint64_t length)
{
bool success = 0;
#ifdef _WIN32
HANDLE hFile = CreateFile (filename, GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
if (hFile != INVALID_HANDLE_VALUE)
tr_sys_file_t fd = tr_sys_file_open (filename, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0666, NULL);
if (fd != TR_BAD_SYS_FILE)
{
LARGE_INTEGER li;
li.QuadPart = length;
success = SetFilePointerEx (hFile, li, NULL, FILE_BEGIN) && SetEndOfFile (hFile);
CloseHandle (hFile);
}
#else
int flags = O_RDWR | O_CREAT | O_LARGEFILE;
int fd = open (filename, flags, 0666);
if (fd >= 0)
{
# ifdef HAVE_FALLOCATE64
if (!success)
success = !fallocate64 (fd, 0, 0, length);
# endif
# ifdef HAVE_XFS_XFS_H
if (!success && platform_test_xfs_fd (fd))
{
xfs_flock64_t fl;
fl.l_whence = 0;
fl.l_start = 0;
fl.l_len = length;
success = !xfsctl (NULL, fd, XFS_IOC_RESVSP64, &fl);
}
# endif
# ifdef __APPLE__
if (!success)
{
fstore_t fst;
fst.fst_flags = F_ALLOCATECONTIG;
fst.fst_posmode = F_PEOFPOSMODE;
fst.fst_offset = 0;
fst.fst_length = length;
fst.fst_bytesalloc = 0;
success = !fcntl (fd, F_PREALLOCATE, &fst);
}
# endif
# ifdef HAVE_POSIX_FALLOCATE
if (!success)
success = !posix_fallocate (fd, 0, length);
# endif
success = tr_sys_file_preallocate (fd, length, 0, NULL);
if (!success) /* if nothing else works, do it the old-fashioned way */
{
@ -154,139 +79,19 @@ preallocate_file_full (const char * filename, uint64_t length)
success = true;
while (success && (length > 0))
{
const int thisPass = MIN (length, sizeof (buf));
success = write (fd, buf, thisPass) == thisPass;
const uint64_t thisPass = MIN (length, sizeof (buf));
uint64_t bytes_written;
success = tr_sys_file_write (fd, buf, thisPass, &bytes_written, NULL) && bytes_written == thisPass;
length -= thisPass;
}
}
close (fd);
tr_sys_file_close (fd, NULL);
}
#endif
return success;
}
/* portability wrapper for fsync (). */
int
tr_fsync (int fd)
{
#ifdef _WIN32
return _commit (fd);
#else
return fsync (fd);
#endif
}
/* Like pread and pwrite, except that the position is undefined afterwards.
And of course they are not thread-safe. */
/* don't use pread/pwrite on old versions of uClibc because they're buggy.
* https://trac.transmissionbt.com/ticket/3826 */
#ifdef __UCLIBC__
#define TR_UCLIBC_CHECK_VERSION(major,minor,micro) \
(__UCLIBC_MAJOR__ > (major) || \
(__UCLIBC_MAJOR__ == (major) && __UCLIBC_MINOR__ > (minor)) || \
(__UCLIBC_MAJOR__ == (major) && __UCLIBC_MINOR__ == (minor) && \
__UCLIBC_SUBLEVEL__ >= (micro)))
#if !TR_UCLIBC_CHECK_VERSION (0,9,28)
#undef HAVE_PREAD
#undef HAVE_PWRITE
#endif
#endif
#ifdef __APPLE__
#define HAVE_PREAD
#define HAVE_PWRITE
#endif
ssize_t
tr_pread (int fd, void *buf, size_t count, off_t offset)
{
#ifdef HAVE_PREAD
return pread (fd, buf, count, offset);
#else
const off_t lrc = lseek (fd, offset, SEEK_SET);
if (lrc < 0)
return -1;
return read (fd, buf, count);
#endif
}
ssize_t
tr_pwrite (int fd, const void *buf, size_t count, off_t offset)
{
#ifdef HAVE_PWRITE
return pwrite (fd, buf, count, offset);
#else
const off_t lrc = lseek (fd, offset, SEEK_SET);
if (lrc < 0)
return -1;
return write (fd, buf, count);
#endif
}
int
tr_prefetch (int fd UNUSED, off_t offset UNUSED, size_t count UNUSED)
{
#ifdef HAVE_POSIX_FADVISE
return posix_fadvise (fd, offset, count, POSIX_FADV_WILLNEED);
#elif defined (__APPLE__)
struct radvisory radv;
radv.ra_offset = offset;
radv.ra_count = count;
return fcntl (fd, F_RDADVISE, &radv);
#else
return 0;
#endif
}
void
tr_set_file_for_single_pass (int fd)
{
if (fd >= 0)
{
/* Set hints about the lookahead buffer and caching. It's okay
for these to fail silently, so don't let them affect errno */
const int err = errno;
#ifdef HAVE_POSIX_FADVISE
posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL);
#endif
#ifdef __APPLE__
fcntl (fd, F_RDAHEAD, 1);
fcntl (fd, F_NOCACHE, 1);
#endif
errno = err;
}
}
static int
open_local_file (const char * filename, int flags)
{
const int fd = open (filename, flags, 0666);
tr_set_file_for_single_pass (fd);
return fd;
}
int
tr_open_file_for_writing (const char * filename)
{
return open_local_file (filename, O_LARGEFILE|O_BINARY|O_CREAT|O_WRONLY);
}
int
tr_open_file_for_scanning (const char * filename)
{
return open_local_file (filename, O_LARGEFILE|O_BINARY|O_SEQUENTIAL|O_RDONLY);
}
void
tr_close_file (int fd)
{
close (fd);
}
/*****
******
******
@ -296,7 +101,7 @@ tr_close_file (int fd)
struct tr_cached_file
{
bool is_writable;
int fd;
tr_sys_file_t fd;
int torrent_id;
tr_file_index_t file_index;
time_t used_at;
@ -307,7 +112,7 @@ cached_file_is_open (const struct tr_cached_file * o)
{
assert (o != NULL);
return o->fd >= 0;
return o->fd != TR_BAD_SYS_FILE;
}
static void
@ -315,14 +120,14 @@ cached_file_close (struct tr_cached_file * o)
{
assert (cached_file_is_open (o));
tr_close_file (o->fd);
o->fd = -1;
tr_sys_file_close (o->fd, NULL);
o->fd = TR_BAD_SYS_FILE;
}
/**
* returns 0 on success, or an errno value on failure.
* errno values include ENOENT if the parent folder doesn't exist,
* plus the errno values set by tr_mkdirp () and open ().
* plus the errno values set by tr_mkdirp () and tr_sys_file_open ().
*/
static int
cached_file_open (struct tr_cached_file * o,
@ -335,6 +140,7 @@ cached_file_open (struct tr_cached_file * o,
tr_sys_path_info info;
bool already_existed;
bool resize_needed;
tr_error * error = NULL;
/* create subfolders, if any */
if (writable)
@ -361,14 +167,15 @@ cached_file_open (struct tr_cached_file * o,
writable |= resize_needed;
/* open the file */
flags = writable ? (O_RDWR | O_CREAT) : O_RDONLY;
flags |= O_LARGEFILE | O_BINARY | O_SEQUENTIAL;
o->fd = open (filename, flags, 0666);
flags = writable ? (TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE) : 0;
flags |= TR_SYS_FILE_READ | TR_SYS_FILE_SEQUENTIAL;
o->fd = tr_sys_file_open (filename, flags, 0666, &error);
if (o->fd == -1)
if (o->fd == TR_BAD_SYS_FILE)
{
const int err = errno;
tr_logAddError (_("Couldn't open \"%1$s\": %2$s"), filename, tr_strerror (err));
const int err = error->code;
tr_logAddError (_("Couldn't open \"%1$s\": %2$s"), filename, error->message);
tr_error_free (error);
return err;
}
@ -378,21 +185,17 @@ cached_file_open (struct tr_cached_file * o,
* http://trac.transmissionbt.com/ticket/2228
* https://bugs.launchpad.net/ubuntu/+source/transmission/+bug/318249
*/
if (resize_needed && (ftruncate (o->fd, file_size) == -1))
if (resize_needed && !tr_sys_file_truncate (o->fd, file_size, &error))
{
const int err = errno;
tr_logAddError (_("Couldn't truncate \"%1$s\": %2$s"), filename, tr_strerror (err));
const int err = error->code;
tr_logAddError (_("Couldn't truncate \"%1$s\": %2$s"), filename, error->message);
tr_error_free (error);
return err;
}
if (writable && !already_existed && (allocation == TR_PREALLOCATE_SPARSE))
preallocate_file_sparse (o->fd, file_size);
/* Many (most?) clients request blocks in ascending order,
* so increase the readahead buffer.
* Also, disable OS-level caching because "inactive memory" angers users. */
tr_set_file_for_single_pass (o->fd);
return 0;
}
@ -410,7 +213,7 @@ static void
fileset_construct (struct tr_fileset * set, int n)
{
struct tr_cached_file * o;
const struct tr_cached_file TR_CACHED_FILE_INIT = { 0, -1, 0, 0, 0 };
const struct tr_cached_file TR_CACHED_FILE_INIT = { false, TR_BAD_SYS_FILE, 0, 0, 0 };
set->begin = tr_new (struct tr_cached_file, n);
set->end = set->begin + n;
@ -567,39 +370,33 @@ tr_fdFileClose (tr_session * s, const tr_torrent * tor, tr_file_index_t i)
/* flush writable files so that their mtimes will be
* up-to-date when this function returns to the caller... */
if (o->is_writable)
tr_fsync (o->fd);
tr_sys_file_flush (o->fd, NULL);
cached_file_close (o);
}
}
int
tr_sys_file_t
tr_fdFileGetCached (tr_session * s, int torrent_id, tr_file_index_t i, bool writable)
{
struct tr_cached_file * o = fileset_lookup (get_fileset (s), torrent_id, i);
if (!o || (writable && !o->is_writable))
return -1;
return TR_BAD_SYS_FILE;
o->used_at = tr_time ();
return o->fd;
}
#ifdef __APPLE__
#define TR_STAT_MTIME(sb)((sb).st_mtimespec.tv_sec)
#else
#define TR_STAT_MTIME(sb)((sb).st_mtime)
#endif
bool
tr_fdFileGetCachedMTime (tr_session * s, int torrent_id, tr_file_index_t i, time_t * mtime)
{
bool success;
struct stat sb;
tr_sys_path_info info;
struct tr_cached_file * o = fileset_lookup (get_fileset (s), torrent_id, i);
if ((success = (o != NULL) && !fstat (o->fd, &sb)))
*mtime = TR_STAT_MTIME (sb);
if ((success = (o != NULL) && tr_sys_file_get_info (o->fd, &info, NULL)))
*mtime = info.last_modified_at;
return success;
}
@ -612,8 +409,8 @@ tr_fdTorrentClose (tr_session * session, int torrent_id)
fileset_close_torrent (get_fileset (session), torrent_id);
}
/* returns an fd on success, or a -1 on failure and sets errno */
int
/* returns an fd on success, or a TR_BAD_SYS_FILE on failure and sets errno */
tr_sys_file_t
tr_fdFileCheckout (tr_session * session,
int torrent_id,
tr_file_index_t i,
@ -636,7 +433,7 @@ tr_fdFileCheckout (tr_session * session,
if (err)
{
errno = err;
return -1;
return TR_BAD_SYS_FILE;
}
dbgmsg ("opened '%s' writable %c", filename, writable?'y':'n');

View File

@ -12,6 +12,7 @@
#endif
#include "transmission.h"
#include "file.h"
#include "net.h"
/**
@ -23,21 +24,6 @@
****
***/
void tr_set_file_for_single_pass (int fd);
int tr_open_file_for_scanning (const char * filename);
int tr_open_file_for_writing (const char * filename);
void tr_close_file (int fd);
int tr_fsync (int fd);
ssize_t tr_pread (int fd, void *buf, size_t count, off_t offset);
ssize_t tr_pwrite (int fd, const void *buf, size_t count, off_t offset);
int tr_prefetch (int fd, off_t offset, size_t count);
/**
* Returns an fd to the specified filename.
*
@ -49,22 +35,22 @@ int tr_prefetch (int fd, off_t offset, size_t count);
* - if do_write is true, the target file is created if necessary.
*
* on success, a file descriptor >= 0 is returned.
* on failure, a -1 is returned and errno is set.
* on failure, a TR_BAD_SYS_FILE is returned and errno is set.
*
* @see tr_fdFileClose
*/
int tr_fdFileCheckout (tr_session * session,
int torrent_id,
tr_file_index_t file_num,
const char * filename,
bool do_write,
tr_preallocation_mode preallocation_mode,
uint64_t preallocation_file_size);
tr_sys_file_t tr_fdFileCheckout (tr_session * session,
int torrent_id,
tr_file_index_t file_num,
const char * filename,
bool do_write,
tr_preallocation_mode preallocation_mode,
uint64_t preallocation_file_size);
int tr_fdFileGetCached (tr_session * session,
int torrent_id,
tr_file_index_t file_num,
bool doWrite);
tr_sys_file_t tr_fdFileGetCached (tr_session * session,
int torrent_id,
tr_file_index_t file_num,
bool doWrite);
bool tr_fdFileGetCachedMTime (tr_session * session,
int torrent_id,

View File

@ -16,7 +16,9 @@
#include "transmission.h"
#include "cache.h" /* tr_cacheReadBlock () */
#include "error.h"
#include "fdlimit.h"
#include "file.h"
#include "inout.h"
#include "log.h"
#include "peer-common.h" /* MAX_BLOCK_SIZE */
@ -46,7 +48,7 @@ readOrWriteBytes (tr_session * session,
void * buf,
size_t buflen)
{
int fd;
tr_sys_file_t fd;
int err = 0;
const bool doWrite = ioMode >= TR_IO_WRITE;
const tr_info * const info = &tor->info;
@ -64,7 +66,7 @@ readOrWriteBytes (tr_session * session,
***/
fd = tr_fdFileGetCached (session, tr_torrentId (tor), fileIndex, doWrite);
if (fd < 0)
if (fd == TR_BAD_SYS_FILE)
{
/* it's not cached, so open/create it now */
char * subpath;
@ -94,7 +96,7 @@ readOrWriteBytes (tr_session * session,
: tor->session->preallocationMode;
if (((fd = tr_fdFileCheckout (session, tor->uniqueId, fileIndex,
filename, doWrite,
prealloc, file->length))) < 0)
prealloc, file->length))) == TR_BAD_SYS_FILE)
{
err = errno;
tr_logAddTorErr (tor, "tr_fdFileCheckout failed for \"%s\": %s",
@ -118,27 +120,29 @@ readOrWriteBytes (tr_session * session,
if (!err)
{
tr_error * error = NULL;
if (ioMode == TR_IO_READ)
{
const int rc = tr_pread (fd, buf, buflen, fileOffset);
if (rc < 0)
if (!tr_sys_file_read_at (fd, buf, buflen, fileOffset, NULL, &error))
{
err = errno;
tr_logAddTorErr (tor, "read failed for \"%s\": %s", file->name, tr_strerror (err));
err = error->code;
tr_logAddTorErr (tor, "read failed for \"%s\": %s", file->name, error->message);
tr_error_free (error);
}
}
else if (ioMode == TR_IO_WRITE)
{
const int rc = tr_pwrite (fd, buf, buflen, fileOffset);
if (rc < 0)
if (!tr_sys_file_write_at (fd, buf, buflen, fileOffset, NULL, &error))
{
err = errno;
tr_logAddTorErr (tor, "write failed for \"%s\": %s", file->name, tr_strerror (err));
err = error->code;
tr_logAddTorErr (tor, "write failed for \"%s\": %s", file->name, error->message);
tr_error_free (error);
}
}
else if (ioMode == TR_IO_PREFETCH)
{
tr_prefetch (fd, fileOffset, buflen);
tr_sys_file_prefetch (fd, fileOffset, buflen, NULL);
}
else
{

View File

@ -14,6 +14,7 @@
#include <unistd.h>
#include "transmission.h"
#include "error.h"
#include "file.h"
#include "platform.h" /* TR_PATH_DELIMETER */
#include "torrent.h"
@ -373,7 +374,7 @@ libttest_zero_torrent_populate (tr_torrent * tor, bool complete)
{
int err;
uint64_t j;
FILE * fp;
tr_sys_file_t fd;
char * path;
char * dirname;
const tr_file * file = &tor->info.files[i];
@ -384,10 +385,10 @@ libttest_zero_torrent_populate (tr_torrent * tor, bool complete)
path = tr_strdup_printf ("%s%c%s", tor->currentDir, TR_PATH_DELIMITER, file->name);
dirname = tr_sys_path_dirname (path, NULL);
tr_mkdirp (dirname, 0700);
fp = fopen (path, "wb+");
fd = tr_sys_file_open (path, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE, 0600, NULL);
for (j=0; j<file->length; ++j)
fputc (((!complete) && (i==0) && (j<tor->info.pieceSize)) ? '\1' : '\0', fp);
fclose (fp);
tr_sys_file_write (fd, ((!complete) && (i==0) && (j<tor->info.pieceSize)) ? "\1" : "\0", 1, NULL, NULL);
tr_sys_file_close (fd, NULL);
tr_free (dirname);
tr_free (path);
@ -450,15 +451,14 @@ build_parent_dir (const char* path)
void
libtest_create_file_with_contents (const char* path, const void* payload, size_t n)
{
FILE * fp;
tr_sys_file_t fd;
const int tmperr = errno;
build_parent_dir (path);
tr_sys_path_remove (path, NULL);
fp = fopen (path, "wb");
fwrite (payload, 1, n, fp);
fclose (fp);
fd = tr_sys_file_open (path, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE, 0600, NULL);
tr_sys_file_write (fd, payload, n, NULL, NULL);
tr_sys_file_close (fd, NULL);
sync ();
@ -474,24 +474,26 @@ libtest_create_file_with_string_contents (const char * path, const char* str)
void
libtest_create_tmpfile_with_contents (char* tmpl, const void* payload, size_t n)
{
int fd;
tr_sys_file_t fd;
const int tmperr = errno;
size_t n_left = n;
uint64_t n_left = n;
tr_error * error = NULL;
build_parent_dir (tmpl);
fd = mkstemp (tmpl);
fd = tr_sys_file_open_temp (tmpl, NULL);
while (n_left > 0)
{
const ssize_t n = write (fd, payload, n_left);
if (n == -1)
uint64_t n;
if (!tr_sys_file_write (fd, payload, n_left, &n, &error))
{
fprintf (stderr, "Error writing '%s': %s\n", tmpl, tr_strerror(errno));
fprintf (stderr, "Error writing '%s': %s\n", tmpl, error->message);
tr_error_free (error);
break;
}
n_left -= n;
}
close (fd);
tr_sys_file_close (fd, NULL);
sync ();

View File

@ -9,11 +9,9 @@
#include <assert.h>
#include <errno.h>
#include <stdio.h> /* FILE, stderr */
#include <stdlib.h> /* qsort */
#include <string.h> /* strcmp, strlen */
#include <unistd.h> /* read () */
#include <dirent.h>
#include <event2/util.h> /* evutil_ascii_strcasecmp () */
@ -21,7 +19,6 @@
#include "transmission.h"
#include "crypto.h" /* tr_sha1 */
#include "error.h"
#include "fdlimit.h" /* tr_open_file_for_scanning () */
#include "file.h"
#include "log.h"
#include "session.h"
@ -228,7 +225,8 @@ getHashInfo (tr_metainfo_builder * b)
uint8_t *buf;
uint64_t totalRemain;
uint64_t off = 0;
int fd;
tr_sys_file_t fd;
tr_error * error = NULL;
if (!b->totalSize)
return ret;
@ -236,16 +234,18 @@ getHashInfo (tr_metainfo_builder * b)
buf = tr_valloc (b->pieceSize);
b->pieceIndex = 0;
totalRemain = b->totalSize;
fd = tr_open_file_for_scanning (b->files[fileIndex].filename);
if (fd < 0)
fd = tr_sys_file_open (b->files[fileIndex].filename, TR_SYS_FILE_READ |
TR_SYS_FILE_SEQUENTIAL, 0, &error);
if (fd == TR_BAD_SYS_FILE)
{
b->my_errno = errno;
b->my_errno = error->code;
tr_strlcpy (b->errfile,
b->files[fileIndex].filename,
sizeof (b->errfile));
b->result = TR_MAKEMETA_IO_READ;
tr_free (buf);
tr_free (ret);
tr_error_free (error);
return NULL;
}
@ -253,34 +253,37 @@ getHashInfo (tr_metainfo_builder * b)
{
uint8_t * bufptr = buf;
const uint32_t thisPieceSize = (uint32_t) MIN (b->pieceSize, totalRemain);
uint32_t leftInPiece = thisPieceSize;
uint64_t leftInPiece = thisPieceSize;
assert (b->pieceIndex < b->pieceCount);
while (leftInPiece)
{
const size_t n_this_pass = (size_t) MIN ((b->files[fileIndex].size - off), leftInPiece);
const ssize_t n_read = read (fd, bufptr, n_this_pass);
const uint64_t n_this_pass = MIN (b->files[fileIndex].size - off, leftInPiece);
uint64_t n_read = 0;
tr_sys_file_read (fd, bufptr, n_this_pass, &n_read, NULL);
bufptr += n_read;
off += n_read;
leftInPiece -= n_read;
if (off == b->files[fileIndex].size)
{
off = 0;
tr_close_file (fd);
fd = -1;
tr_sys_file_close (fd, NULL);
fd = TR_BAD_SYS_FILE;
if (++fileIndex < b->fileCount)
{
fd = tr_open_file_for_scanning (b->files[fileIndex].filename);
if (fd < 0)
fd = tr_sys_file_open (b->files[fileIndex].filename, TR_SYS_FILE_READ |
TR_SYS_FILE_SEQUENTIAL, 0, &error);
if (fd == TR_BAD_SYS_FILE)
{
b->my_errno = errno;
b->my_errno = error->code;
tr_strlcpy (b->errfile,
b->files[fileIndex].filename,
sizeof (b->errfile));
b->result = TR_MAKEMETA_IO_READ;
tr_free (buf);
tr_free (ret);
tr_error_free (error);
return NULL;
}
}
@ -306,8 +309,8 @@ getHashInfo (tr_metainfo_builder * b)
|| (walk - ret == (int)(SHA_DIGEST_LENGTH * b->pieceCount)));
assert (b->abortFlag || !totalRemain);
if (fd >= 0)
tr_close_file (fd);
if (fd != TR_BAD_SYS_FILE)
tr_sys_file_close (fd, NULL);
tr_free (buf);
return ret;

View File

@ -565,123 +565,3 @@ tr_getWebClientDir (const tr_session * session UNUSED)
return s;
}
#ifdef _WIN32
/* The following mmap functions are by Joerg Walter, and were taken from
* his paper at: http://www.genesys-e.de/jwalter/mix4win.htm */
#if defined (_MSC_VER)
__declspec (align (4)) static LONG volatile g_sl;
#else
static LONG volatile g_sl __attribute__((aligned (4)));
#endif
/* Wait for spin lock */
static int
slwait (LONG volatile *sl)
{
while (InterlockedCompareExchange (sl, 1, 0) != 0)
Sleep (0);
return 0;
}
/* Release spin lock */
static int
slrelease (LONG volatile *sl)
{
InterlockedExchange (sl, 0);
return 0;
}
/* getpagesize for windows */
static long
getpagesize (void)
{
static long g_pagesize = 0;
if (!g_pagesize)
{
SYSTEM_INFO system_info;
GetSystemInfo (&system_info);
g_pagesize = system_info.dwPageSize;
}
return g_pagesize;
}
static long
getregionsize (void)
{
static long g_regionsize = 0;
if (!g_regionsize)
{
SYSTEM_INFO system_info;
GetSystemInfo (&system_info);
g_regionsize = system_info.dwAllocationGranularity;
}
return g_regionsize;
}
void *
mmap (void *ptr, long size, long prot, long type, long handle, long arg)
{
static long g_pagesize;
static long g_regionsize;
/* Wait for spin lock */
slwait (&g_sl);
/* First time initialization */
if (!g_pagesize)
g_pagesize = getpagesize ();
if (!g_regionsize)
g_regionsize = getregionsize ();
/* Allocate this */
ptr = VirtualAlloc (ptr, size, MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);
if (!ptr)
{
ptr = (void *) -1;
goto mmap_exit;
}
mmap_exit:
/* Release spin lock */
slrelease (&g_sl);
return ptr;
}
long
munmap (void *ptr, long size)
{
static long g_pagesize;
static long g_regionsize;
int rc = -1;
/* Wait for spin lock */
slwait (&g_sl);
/* First time initialization */
if (!g_pagesize)
g_pagesize = getpagesize ();
if (!g_regionsize)
g_regionsize = getregionsize ();
/* Free this */
if (!VirtualFree (ptr, 0, MEM_RELEASE))
goto munmap_exit;
rc = 0;
munmap_exit:
/* Release spin lock */
slrelease (&g_sl);
return rc;
}
#endif

View File

@ -77,12 +77,6 @@ void tr_lockUnlock (tr_lock *);
/** @brief return nonzero if the specified lock is locked */
int tr_lockHave (const tr_lock *);
#ifdef _WIN32
void * mmap (void *ptr, long size, long prot, long type, long handle, long arg);
long munmap (void *ptr, long size);
#endif
/* @} */
#endif

View File

@ -11,8 +11,6 @@
#include <errno.h>
#include <string.h> /* memcpy */
#include <unistd.h> /* close */
#include <zlib.h>
#include <event2/buffer.h>

View File

@ -19,6 +19,7 @@
#include "transmission.h"
#include "completion.h"
#include "error.h"
#include "fdlimit.h"
#include "file.h"
#include "log.h"
@ -1487,13 +1488,14 @@ gotNewBlocklist (tr_session * session,
}
else /* successfully fetched the blocklist... */
{
int fd;
tr_sys_file_t fd;
int err;
char * filename;
z_stream stream;
const char * configDir = tr_sessionGetConfigDir (session);
const size_t buflen = 1024 * 128; /* 128 KiB buffer */
uint8_t * buf = tr_valloc (buflen);
tr_error * error = NULL;
/* this is an odd Magic Number required by zlib to enable gz support.
See zlib's inflateInit2 () documentation for a full description */
@ -1506,10 +1508,13 @@ gotNewBlocklist (tr_session * session,
stream.avail_in = response_byte_count;
inflateInit2 (&stream, windowBits);
filename = tr_buildPath (configDir, "blocklist.tmp", NULL);
fd = tr_open_file_for_writing (filename);
if (fd < 0)
tr_snprintf (result, sizeof (result), _("Couldn't save file \"%1$s\": %2$s"), filename, tr_strerror (errno));
filename = tr_buildPath (configDir, "blocklist.tmp.XXXXXX", NULL);
fd = tr_sys_file_open_temp (filename, &error);
if (fd == TR_BAD_SYS_FILE)
{
tr_snprintf (result, sizeof (result), _("Couldn't save file \"%1$s\": %2$s"), filename, error->message);
tr_error_clear (&error);
}
for (;;)
{
@ -1519,10 +1524,10 @@ gotNewBlocklist (tr_session * session,
if (stream.avail_out < buflen)
{
const int e = write (fd, buf, buflen - stream.avail_out);
if (e < 0)
if (!tr_sys_file_write (fd, buf, buflen - stream.avail_out, NULL, &error))
{
tr_snprintf (result, sizeof (result), _("Couldn't save file \"%1$s\": %2$s"), filename, tr_strerror (errno));
tr_snprintf (result, sizeof (result), _("Couldn't save file \"%1$s\": %2$s"), filename, error->message);
tr_error_clear (&error);
break;
}
}
@ -1538,10 +1543,13 @@ gotNewBlocklist (tr_session * session,
inflateEnd (&stream);
if (err == Z_DATA_ERROR) /* couldn't inflate it... it's probably already uncompressed */
if (write (fd, response, response_byte_count) < 0)
tr_snprintf (result, sizeof (result), _("Couldn't save file \"%1$s\": %2$s"), filename, tr_strerror (errno));
if (!tr_sys_file_write (fd, response, response_byte_count, NULL, &error))
{
tr_snprintf (result, sizeof (result), _("Couldn't save file \"%1$s\": %2$s"), filename, error->message);
tr_error_clear (&error);
}
tr_close_file(fd);
tr_sys_file_close (fd, NULL);
if (*result)
{

View File

@ -155,19 +155,19 @@ tr_torrentGetMetadataPiece (tr_torrent * tor, int piece, int * len)
if (tr_torrentHasMetadata (tor))
{
FILE * fp;
tr_sys_file_t fd;
ensureInfoDictOffsetIsCached (tor);
assert (tor->infoDictLength > 0);
assert (tor->infoDictOffset >= 0);
fp = fopen (tor->info.torrent, "rb");
if (fp != NULL)
fd = tr_sys_file_open (tor->info.torrent, TR_SYS_FILE_READ, 0, NULL);
if (fd != TR_BAD_SYS_FILE)
{
const int o = piece * METADATA_PIECE_SIZE;
if (!fseek (fp, tor->infoDictOffset + o, SEEK_SET))
if (tr_sys_file_seek (fd, tor->infoDictOffset + o, TR_SEEK_SET, NULL, NULL))
{
const int l = o + METADATA_PIECE_SIZE <= tor->infoDictLength
? METADATA_PIECE_SIZE
@ -176,8 +176,8 @@ tr_torrentGetMetadataPiece (tr_torrent * tor, int piece, int * len)
if (0<l && l<=METADATA_PIECE_SIZE)
{
char * buf = tr_new (char, l);
const int n = fread (buf, 1, l, fp);
if (n == l)
uint64_t n;
if (tr_sys_file_read (fd, buf, l, &n, NULL) && n == (unsigned int) l)
{
*len = l;
ret = buf;
@ -188,7 +188,7 @@ tr_torrentGetMetadataPiece (tr_torrent * tor, int piece, int * len)
}
}
fclose (fp);
tr_sys_file_close (fd, NULL);
}
}

View File

@ -28,14 +28,14 @@
#include <stdlib.h>
#include <string.h> /* strerror (), memset (), memmem () */
#include <time.h> /* nanosleep () */
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_ICONV_OPEN
#include <iconv.h>
#endif
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h> /* stat (), getpagesize () */
#include <unistd.h> /* getpagesize () */
#include <event2/buffer.h>
#include <event2/event.h>
@ -48,7 +48,6 @@
#include "transmission.h"
#include "error.h"
#include "fdlimit.h"
#include "file.h"
#include "ConvertUTF.h"
#include "list.h"
@ -221,8 +220,7 @@ tr_loadFile (const char * path,
{
uint8_t * buf;
tr_sys_path_info info;
int fd;
ssize_t n;
tr_sys_file_t fd;
tr_error * error = NULL;
const char * const err_fmt = _("Couldn't read \"%1$s\": %2$s");
@ -248,11 +246,12 @@ tr_loadFile (const char * path,
assert (info.size <= SIZE_MAX);
/* Load the torrent file into our buffer */
fd = tr_open_file_for_scanning (path);
if (fd < 0)
fd = tr_sys_file_open (path, TR_SYS_FILE_READ | TR_SYS_FILE_SEQUENTIAL, 0, &error);
if (fd == TR_BAD_SYS_FILE)
{
const int err = errno;
tr_logAddError (err_fmt, path, tr_strerror (errno));
const int err = error->code;
tr_logAddError (err_fmt, path, error->message);
tr_error_free (error);
errno = err;
return NULL;
}
@ -261,22 +260,22 @@ tr_loadFile (const char * path,
{
const int err = errno;
tr_logAddError (err_fmt, path, _("Memory allocation failed"));
tr_close_file (fd);
tr_sys_file_close (fd, NULL);
errno = err;
return NULL;
}
n = read (fd, buf, (size_t)info.size);
if (n == -1)
if (!tr_sys_file_read (fd, buf, info.size, NULL, &error))
{
const int err = errno;
tr_logAddError (err_fmt, path, tr_strerror (errno));
tr_close_file (fd);
const int err = error->code;
tr_logAddError (err_fmt, path, error->message);
tr_sys_file_close (fd, NULL);
free (buf);
tr_error_free (error);
errno = err;
return NULL;
}
tr_close_file (fd);
tr_sys_file_close (fd, NULL);
buf[info.size] = '\0';
*size = info.size;
return buf;
@ -1544,11 +1543,11 @@ tr_strratio (char * buf, size_t buflen, double ratio, const char * infinity)
int
tr_moveFile (const char * oldpath, const char * newpath, bool * renamed)
{
int in;
int out;
tr_sys_file_t in;
tr_sys_file_t out;
char * buf;
tr_sys_path_info info;
off_t bytesLeft;
uint64_t bytesLeft;
const size_t buflen = 1024 * 128; /* 128 KiB buffer */
tr_error * error = NULL;
@ -1586,26 +1585,24 @@ tr_moveFile (const char * oldpath, const char * newpath, bool * renamed)
}
/* copy the file */
in = tr_open_file_for_scanning (oldpath);
out = tr_open_file_for_writing (newpath);
in = tr_sys_file_open (oldpath, TR_SYS_FILE_READ | TR_SYS_FILE_SEQUENTIAL, 0, NULL);
out = tr_sys_file_open (newpath, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE, 0666, NULL);
buf = tr_valloc (buflen);
while (bytesLeft > 0)
{
ssize_t bytesWritten;
const off_t bytesThisPass = MIN (bytesLeft, (off_t)buflen);
const int numRead = read (in, buf, bytesThisPass);
if (numRead < 0)
const uint64_t bytesThisPass = MIN (bytesLeft, buflen);
uint64_t numRead, bytesWritten;
if (!tr_sys_file_read (in, buf, bytesThisPass, &numRead, NULL))
break;
bytesWritten = write (out, buf, numRead);
if (bytesWritten < 0)
if (!tr_sys_file_write (out, buf, numRead, &bytesWritten, NULL))
break;
bytesLeft -= bytesWritten;
}
/* cleanup */
tr_free (buf);
tr_close_file (out);
tr_close_file (in);
tr_sys_file_close (out, NULL);
tr_sys_file_close (in, NULL);
if (bytesLeft != 0)
return -1;

View File

@ -9,24 +9,20 @@
#include <assert.h>
#include <errno.h>
#include <stdlib.h> /* strtod(), realloc(), qsort(), mkstemp() */
#include <stdlib.h> /* strtod(), realloc(), qsort() */
#include <string.h>
#ifdef _WIN32 /* tr_mkstemp() */
#include <fcntl.h>
#ifdef _WIN32
#include <share.h>
#include <sys/stat.h>
#endif
#include <locale.h> /* setlocale() */
#include <unistd.h> /* write() */
#include <event2/buffer.h>
#define __LIBTRANSMISSION_VARIANT_MODULE___
#include "transmission.h"
#include "ConvertUTF.h"
#include "fdlimit.h" /* tr_close_file() */
#include "error.h"
#include "file.h"
#include "log.h"
@ -1125,55 +1121,28 @@ tr_variantToStr (const tr_variant * v, tr_variant_fmt fmt, int * len)
return ret;
}
/* portability wrapper for mkstemp(). */
static int
tr_mkstemp (char * template)
{
#ifdef _WIN32
const int n = strlen (template) + 1;
const int flags = O_RDWR | O_BINARY | O_CREAT | O_EXCL | _O_SHORT_LIVED;
const mode_t mode = _S_IREAD | _S_IWRITE;
wchar_t templateUTF16[n];
if (MultiByteToWideChar(CP_UTF8, 0, template, -1, templateUTF16, n))
{
_wmktemp(templateUTF16);
WideCharToMultiByte(CP_UTF8, 0, templateUTF16, -1, template, n, NULL, NULL);
return _wopen(chkFilename(templateUTF16), flags, mode);
}
errno = EINVAL;
return -1;
#else
return mkstemp (template);
#endif
}
int
tr_variantToFile (const tr_variant * v,
tr_variant_fmt fmt,
const char * filename)
{
char * tmp;
int fd;
tr_sys_file_t fd;
int err = 0;
char * real_filename;
tr_error * error = NULL;
/* follow symlinks to find the "real" file, to make sure the temporary
* we build with tr_mkstemp() is created on the right partition */
* we build with tr_sys_file_open_temp() is created on the right partition */
if ((real_filename = tr_sys_path_resolve (filename, NULL)) != NULL)
filename = real_filename;
/* if the file already exists, try to move it out of the way & keep it as a backup */
tmp = tr_strdup_printf ("%s.tmp.XXXXXX", filename);
fd = tr_mkstemp (tmp);
tr_set_file_for_single_pass (fd);
if (fd >= 0)
fd = tr_sys_file_open_temp (tmp, &error);
if (fd != TR_BAD_SYS_FILE)
{
int nleft;
uint64_t nleft;
/* save the variant to a temporary file */
{
@ -1183,34 +1152,31 @@ tr_variantToFile (const tr_variant * v,
while (nleft > 0)
{
const int n = write (fd, walk, nleft);
if (n >= 0)
uint64_t n;
if (!tr_sys_file_write (fd, walk, nleft, &n, &error))
{
nleft -= n;
walk += n;
}
else if (errno != EAGAIN)
{
err = errno;
err = error->code;
break;
}
nleft -= n;
walk += n;
}
evbuffer_free (buf);
}
tr_sys_file_close (fd, NULL);
if (nleft > 0)
{
tr_logAddError (_("Couldn't save temporary file \"%1$s\": %2$s"), tmp, tr_strerror (err));
tr_close_file (fd);
tr_logAddError (_("Couldn't save temporary file \"%1$s\": %2$s"), tmp, error->message);
tr_sys_path_remove (tmp, NULL);
tr_error_free (error);
}
else
{
tr_error * error = NULL;
tr_close_file (fd);
tr_error_clear (&error);
if (tr_sys_path_rename (tmp, filename, &error))
{
tr_logAddInfo (_("Saved \"%s\""), filename);
@ -1226,8 +1192,9 @@ tr_variantToFile (const tr_variant * v,
}
else
{
err = errno;
tr_logAddError (_("Couldn't save temporary file \"%1$s\": %2$s"), tmp, tr_strerror (err));
err = error->code;
tr_logAddError (_("Couldn't save temporary file \"%1$s\": %2$s"), tmp, error->message);
tr_error_free (error);
}
tr_free (tmp);

View File

@ -19,7 +19,7 @@
#include "transmission.h"
#include "completion.h"
#include "fdlimit.h"
#include "file.h"
#include "list.h"
#include "log.h"
#include "platform.h" /* tr_lock () */
@ -41,8 +41,8 @@ verifyTorrent (tr_torrent * tor, bool * stopFlag)
{
time_t end;
SHA_CTX sha;
int fd = -1;
int64_t filePos = 0;
tr_sys_file_t fd = TR_BAD_SYS_FILE;
uint64_t filePos = 0;
bool changed = 0;
bool hadPiece = 0;
time_t lastSleptAt = 0;
@ -60,8 +60,8 @@ verifyTorrent (tr_torrent * tor, bool * stopFlag)
tr_torrentSetChecked (tor, 0);
while (!*stopFlag && (pieceIndex < tor->info.pieceCount))
{
uint32_t leftInPiece;
uint32_t bytesThisPass;
uint64_t leftInPiece;
uint64_t bytesThisPass;
uint64_t leftInFile;
const tr_file * file = &tor->info.files[fileIndex];
@ -70,10 +70,11 @@ verifyTorrent (tr_torrent * tor, bool * stopFlag)
hadPiece = tr_torrentPieceIsComplete (tor, pieceIndex);
/* if we're starting a new file... */
if (!filePos && (fd<0) && (fileIndex!=prevFileIndex))
if (filePos == 0 && fd == TR_BAD_SYS_FILE && fileIndex != prevFileIndex)
{
char * filename = tr_torrentFindFile (tor, fileIndex);
fd = filename == NULL ? -1 : tr_open_file_for_scanning (filename);
fd = filename == NULL ? TR_BAD_SYS_FILE : tr_sys_file_open (filename,
TR_SYS_FILE_READ | TR_SYS_FILE_SEQUENTIAL, 0, NULL);
tr_free (filename);
prevFileIndex = fileIndex;
}
@ -85,12 +86,12 @@ verifyTorrent (tr_torrent * tor, bool * stopFlag)
bytesThisPass = MIN (bytesThisPass, buflen);
/* read a bit */
if (fd >= 0)
if (fd != TR_BAD_SYS_FILE)
{
const ssize_t numRead = tr_pread (fd, buffer, bytesThisPass, filePos);
if (numRead > 0)
uint64_t numRead;
if (tr_sys_file_read_at (fd, buffer, bytesThisPass, filePos, &numRead, NULL) && numRead > 0)
{
bytesThisPass = (uint32_t)numRead;
bytesThisPass = numRead;
SHA1_Update (&sha, buffer, bytesThisPass);
#if defined HAVE_POSIX_FADVISE && defined POSIX_FADV_DONTNEED
posix_fadvise (fd, filePos, bytesThisPass, POSIX_FADV_DONTNEED);
@ -140,10 +141,10 @@ verifyTorrent (tr_torrent * tor, bool * stopFlag)
/* if we're finishing a file... */
if (leftInFile == 0)
{
if (fd >= 0)
if (fd != TR_BAD_SYS_FILE)
{
tr_close_file (fd);
fd = -1;
tr_sys_file_close (fd, NULL);
fd = TR_BAD_SYS_FILE;
}
fileIndex++;
filePos = 0;
@ -151,8 +152,8 @@ verifyTorrent (tr_torrent * tor, bool * stopFlag)
}
/* cleanup */
if (fd >= 0)
tr_close_file (fd);
if (fd != TR_BAD_SYS_FILE)
tr_sys_file_close (fd, NULL);
free (buffer);
/* stopwatch */