diff --git a/libtransmission/blocklist-test.c b/libtransmission/blocklist-test.c
index 4468473..b83cefb 100644
--- a/libtransmission/blocklist-test.c
+++ b/libtransmission/blocklist-test.c
@@ -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 ();
 }
diff --git a/libtransmission/blocklist.c b/libtransmission/blocklist.c
index 6c75f03..987b205 100644
--- a/libtransmission/blocklist.c
+++ b/libtransmission/blocklist.c
@@ -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;
 
diff --git a/libtransmission/fdlimit.c b/libtransmission/fdlimit.c
index 5926c16..cf518b1 100644
--- a/libtransmission/fdlimit.c
+++ b/libtransmission/fdlimit.c
@@ -7,38 +7,16 @@
  * $Id: fdlimit.c 14316 2014-07-04 00:00:07Z livings124 $
  */
 
-#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');
diff --git a/libtransmission/fdlimit.h b/libtransmission/fdlimit.h
index 3b44a3e..9010fc4 100644
--- a/libtransmission/fdlimit.h
+++ b/libtransmission/fdlimit.h
@@ -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);
-
-int tr_fdFileGetCached (tr_session             * session,
-                        int                      torrent_id,
-                        tr_file_index_t          file_num,
-                        bool                  doWrite);
+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);
+
+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,
diff --git a/libtransmission/inout.c b/libtransmission/inout.c
index 45aac50..580180e 100644
--- a/libtransmission/inout.c
+++ b/libtransmission/inout.c
@@ -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
         {
diff --git a/libtransmission/libtransmission-test.c b/libtransmission/libtransmission-test.c
index d9af33e..236e005 100644
--- a/libtransmission/libtransmission-test.c
+++ b/libtransmission/libtransmission-test.c
@@ -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 ();
 
diff --git a/libtransmission/makemeta.c b/libtransmission/makemeta.c
index 8dd4d26..1a06885 100644
--- a/libtransmission/makemeta.c
+++ b/libtransmission/makemeta.c
@@ -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;
diff --git a/libtransmission/platform.c b/libtransmission/platform.c
index bb9d74d..df5c8d7 100644
--- a/libtransmission/platform.c
+++ b/libtransmission/platform.c
@@ -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
diff --git a/libtransmission/platform.h b/libtransmission/platform.h
index 7d81d7f..a58a925 100644
--- a/libtransmission/platform.h
+++ b/libtransmission/platform.h
@@ -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
diff --git a/libtransmission/rpc-server.c b/libtransmission/rpc-server.c
index 8f8de6e..bca29e3 100644
--- a/libtransmission/rpc-server.c
+++ b/libtransmission/rpc-server.c
@@ -11,8 +11,6 @@
 #include <errno.h>
 #include <string.h> /* memcpy */
 
-#include <unistd.h>    /* close */
-
 #ifdef HAVE_ZLIB
  #include <zlib.h>
 #endif
diff --git a/libtransmission/rpcimpl.c b/libtransmission/rpcimpl.c
index c426827..aa0a5f6 100644
--- a/libtransmission/rpcimpl.c
+++ b/libtransmission/rpcimpl.c
@@ -21,6 +21,7 @@
 
 #include "transmission.h"
 #include "completion.h"
+#include "error.h"
 #include "fdlimit.h"
 #include "file.h"
 #include "log.h"
@@ -1489,13 +1490,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 */
@@ -1508,10 +1510,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 (;;)
         {
@@ -1521,10 +1526,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;
                 }
             }
@@ -1540,10 +1545,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)
         {
diff --git a/libtransmission/torrent-magnet.c b/libtransmission/torrent-magnet.c
index 9b73058..afea466 100644
--- a/libtransmission/torrent-magnet.c
+++ b/libtransmission/torrent-magnet.c
@@ -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);
         }
     }
 
diff --git a/libtransmission/utils.c b/libtransmission/utils.c
index baf4dd1..1ebf9aa 100644
--- a/libtransmission/utils.c
+++ b/libtransmission/utils.c
@@ -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;
 
diff --git a/libtransmission/variant.c b/libtransmission/variant.c
index 126132d..c2cffb9 100644
--- a/libtransmission/variant.c
+++ b/libtransmission/variant.c
@@ -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)
-              {
-                nleft -= n;
-                walk += n;
-              }
-            else if (errno != EAGAIN)
+            uint64_t n;
+            if (!tr_sys_file_write (fd, walk, nleft, &n, &error))
               {
-                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);
diff --git a/libtransmission/verify.c b/libtransmission/verify.c
index a698500..eec0e3a 100644
--- a/libtransmission/verify.c
+++ b/libtransmission/verify.c
@@ -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 */
