]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/libs/filesystem/src/operations.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / filesystem / src / operations.cpp
index 035612cf50309fc7c9b7246f87e8d81915fe7310..306875c5fb7b6e0dcb2f78241d9f9dd10700ae54 100644 (file)
@@ -8,47 +8,83 @@
 
 //  See library home page at http://www.boost.org/libs/filesystem
 
-//--------------------------------------------------------------------------------------// 
+//--------------------------------------------------------------------------------------//
 
-//  define 64-bit offset macros BEFORE including boost/config.hpp (see ticket #5355) 
-#if !(defined(__HP_aCC) && defined(_ILP32) && !defined(_STATVFS_ACPP_PROBLEMS_FIXED))
-#define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect,
-#endif
-#if !defined(__PGI)
-#define __USE_FILE_OFFSET64 // but that is harmless on Windows and on POSIX
-      // 64-bit systems or on 32-bit systems which don't have files larger 
-      // than can be represented by a traditional POSIX/UNIX off_t type. 
-      // OTOH, defining them should kick in 64-bit off_t's (and thus 
-      // st_size)on 32-bit systems that provide the Large File
-      // Support (LFS)interface, such as Linux, Solaris, and IRIX.
-      // The defines are given before any headers are included to
-      // ensure that they are available to all included headers.
-      // That is required at least on Solaris, and possibly on other
-      // systems as well.
+//  define 64-bit offset macros BEFORE including boost/config.hpp (see ticket #5355)
+#if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ < 24
+// Android fully supports 64-bit file offsets only for API 24 and above.
+//
+// Trying to define _FILE_OFFSET_BITS=64 for APIs below 24
+// leads to compilation failure for one or another reason,
+// depending on target Android API level, Android NDK version,
+// used STL, order of include paths and more.
+// For more information, please see:
+// - https://github.com/boostorg/filesystem/issues/65
+// - https://github.com/boostorg/filesystem/pull/69
+//
+// Android NDK developers consider it the expected behavior.
+// See their official position here:
+// - https://github.com/android-ndk/ndk/issues/501#issuecomment-326447479
+// - https://android.googlesource.com/platform/bionic/+/a34817457feee026e8702a1d2dffe9e92b51d7d1/docs/32-bit-abi.md#32_bit-abi-bugs
+//
+// Thus we do not define _FILE_OFFSET_BITS in such case.
 #else
+// Defining _FILE_OFFSET_BITS=64 should kick in 64-bit off_t's
+// (and thus st_size) on 32-bit systems that provide the Large File
+// Support (LFS) interface, such as Linux, Solaris, and IRIX.
+//
+// At the time of this comment writing (March 2018), on most systems
+// _FILE_OFFSET_BITS=64 definition is harmless:
+// either the definition is supported and enables 64-bit off_t,
+// or the definition is not supported and is ignored, in which case
+// off_t does not change its default size for the target system
+// (which may be 32-bit or 64-bit already).
+// Thus it makes sense to have _FILE_OFFSET_BITS=64 defined by default,
+// instead of listing every system that supports the definition.
+// Those few systems, on which _FILE_OFFSET_BITS=64 is harmful,
+// for example this definition causes compilation failure on those systems,
+// should be exempt from defining _FILE_OFFSET_BITS by adding
+// an appropriate #elif block above with the appropriate comment.
+//
+// _FILE_OFFSET_BITS must be defined before any headers are included
+// to ensure that the definition is available to all included headers.
+// That is required at least on Solaris, and possibly on other
+// systems as well.
 #define _FILE_OFFSET_BITS 64
 #endif
 
-// define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows
-// the library is being built (possibly exporting rather than importing code)
-#define BOOST_FILESYSTEM_SOURCE 
-
-#ifndef BOOST_SYSTEM_NO_DEPRECATED 
+#ifndef BOOST_SYSTEM_NO_DEPRECATED
 # define BOOST_SYSTEM_NO_DEPRECATED
 #endif
 
 #ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS  // Sun readdir_r()needs this
+# define _POSIX_PTHREAD_SEMANTICS  // Sun readdir_r() needs this
 #endif
 
+// Include Boost.Predef first so that windows.h is guaranteed to be not included
+#include <boost/predef/os/windows.h>
+#if BOOST_OS_WINDOWS
+#include <boost/winapi/config.hpp>
+#endif
+
+#include <boost/filesystem/config.hpp>
 #include <boost/filesystem/operations.hpp>
-#include <boost/scoped_array.hpp>
+#include <boost/filesystem/file_status.hpp>
+#include <boost/filesystem/exception.hpp>
+#include <boost/filesystem/directory.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/smart_ptr/scoped_array.hpp>
 #include <boost/detail/workaround.hpp>
-#include <vector> 
+#include <boost/cstdint.hpp>
+#include <boost/assert.hpp>
+#include <new> // std::bad_alloc
+#include <limits>
+#include <string>
+#include <cstddef>
 #include <cstdlib>     // for malloc, free
 #include <cstring>
 #include <cstdio>      // for remove, rename
-#if defined(__QNXNTO__)  // see ticket #5355 
+#if defined(__QNXNTO__)  // see ticket #5355
 # include <stdio.h>
 #endif
 #include <cerrno>
 # include <iostream>
 #endif
 
-namespace fs = boost::filesystem;
-using boost::filesystem::path;
-using boost::filesystem::filesystem_error;
-using boost::filesystem::perms;
-using boost::system::error_code;
-using boost::system::error_category;
-using boost::system::system_category;
-using std::string;
-using std::wstring;
-
 # ifdef BOOST_POSIX_API
 
 #   include <sys/types.h>
@@ -88,26 +114,20 @@ using std::wstring;
 #     define BOOST_STATVFS statfs
 #     define BOOST_STATVFS_F_FRSIZE static_cast<boost::uintmax_t>(vfs.f_bsize)
 #   endif
-#   include <dirent.h>
 #   include <unistd.h>
 #   include <fcntl.h>
-#   include <utime.h>
+#   if _POSIX_C_SOURCE < 200809L
+#     include <utime.h>
+#   endif
 #   include "limits.h"
 
-# else // BOOST_WINDOW_API
+# else // BOOST_WINDOWS_API
 
-#   if (defined(__MINGW32__) || defined(__CYGWIN__)) && !defined(WINVER)
-      // Versions of MinGW or Cygwin that support Filesystem V3 support at least WINVER 0x501.
-      // See MinGW's windef.h
-#     define WINVER 0x501
-#   endif
+#   include <boost/winapi/dll.hpp> // get_proc_address, GetModuleHandleW
 #   include <cwchar>
 #   include <io.h>
 #   include <windows.h>
 #   include <winnt.h>
-#   if !defined(_WIN32_WINNT)
-#     define  _WIN32_WINNT   0x0500
-#   endif
 #   if defined(__BORLANDC__) || defined(__MWERKS__)
 #     if defined(__BORLANDC__)
         using std::time_t;
@@ -117,7 +137,22 @@ using std::wstring;
 #     include <sys/utime.h>
 #   endif
 
-//  REPARSE_DATA_BUFFER related definitions are found in ntifs.h, which is part of the 
+#include "windows_tools.hpp"
+
+# endif  // BOOST_WINDOWS_API
+
+#include "error_handling.hpp"
+
+namespace fs = boost::filesystem;
+using boost::filesystem::path;
+using boost::filesystem::filesystem_error;
+using boost::filesystem::perms;
+using boost::system::error_code;
+using boost::system::system_category;
+
+# if defined(BOOST_WINDOWS_API)
+
+//  REPARSE_DATA_BUFFER related definitions are found in ntifs.h, which is part of the
 //  Windows Device Driver Kit. Since that's inconvenient, the definitions are provided
 //  here. See http://msdn.microsoft.com/en-us/library/ms791514.aspx
 
@@ -149,7 +184,7 @@ typedef struct _REPARSE_DATA_BUFFER {
       USHORT  PrintNameOffset;
       USHORT  PrintNameLength;
       WCHAR  PathBuffer[1];
-      } MountPointReparseBuffer;
+    } MountPointReparseBuffer;
     struct {
       UCHAR  DataBuffer[1];
     } GenericReparseBuffer;
@@ -170,32 +205,11 @@ typedef struct _REPARSE_DATA_BUFFER {
 # endif
 
 # ifndef IO_REPARSE_TAG_SYMLINK
-#   define IO_REPARSE_TAG_SYMLINK (0xA000000CL)       
+#   define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
 # endif
 
-inline std::wstring wgetenv(const wchar_t* name)
-{
-  // use vector since for C++03 basic_string is not required to be contiguous
-  std::vector<wchar_t> buf(::GetEnvironmentVariableW(name, NULL, 0));
-
-  // C++03 vector does not have data() so use &buf[0]
-  return (buf.empty()
-    || ::GetEnvironmentVariableW(name, &buf[0], static_cast<DWORD>(buf.size())) == 0)
-    ? std::wstring() : std::wstring(&buf[0]);
-}
-
 # endif  // BOOST_WINDOWS_API
 
-//  BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in
-//  dir_itr_increment. The config tests are placed here because some of the
-//  macros being tested come from dirent.h.
-//
-// TODO: find out what macros indicate dirent::d_type present in more libraries
-# if defined(BOOST_WINDOWS_API)\
-  || defined(_DIRENT_HAVE_D_TYPE)// defined by GNU C library if d_type present
-#   define BOOST_FILESYSTEM_STATUS_CACHE
-# endif
-
 //  POSIX/Windows macros  ----------------------------------------------------//
 
 //  Portions of the POSIX and Windows API's are very similar, except for name,
@@ -207,10 +221,6 @@ inline std::wstring wgetenv(const wchar_t* name)
 
 # if defined(BOOST_POSIX_API)
 
-typedef int err_t;
-
-//  POSIX uses a 0 return to indicate success
-#   define BOOST_ERRNO    errno 
 #   define BOOST_SET_CURRENT_DIRECTORY(P)(::chdir(P)== 0)
 #   define BOOST_CREATE_DIRECTORY(P)(::mkdir(P, S_IRWXU|S_IRWXG|S_IRWXO)== 0)
 #   define BOOST_CREATE_HARD_LINK(F,T)(::link(T, F)== 0)
@@ -223,15 +233,8 @@ typedef int err_t;
 #   define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0)
 #   define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0)
 
-#   define BOOST_ERROR_NOT_SUPPORTED ENOSYS
-#   define BOOST_ERROR_ALREADY_EXISTS EEXIST
-
 # else  // BOOST_WINDOWS_API
 
-typedef DWORD err_t;
-
-//  Windows uses a non-0 return to indicate success
-#   define BOOST_ERRNO    ::GetLastError()
 #   define BOOST_SET_CURRENT_DIRECTORY(P)(::SetCurrentDirectoryW(P)!= 0)
 #   define BOOST_CREATE_DIRECTORY(P)(::CreateDirectoryW(P, 0)!= 0)
 #   define BOOST_CREATE_HARD_LINK(F,T)(create_hard_link_api(F, T, 0)!= 0)
@@ -244,170 +247,120 @@ typedef DWORD err_t;
 #   define BOOST_RESIZE_FILE(P,SZ)(resize_file_api(P, SZ)!= 0)
 #   define BOOST_READ_SYMLINK(P,T)
 
-#   define BOOST_ERROR_ALREADY_EXISTS ERROR_ALREADY_EXISTS
-#   define BOOST_ERROR_NOT_SUPPORTED ERROR_NOT_SUPPORTED
-
 # endif
 
+namespace boost {
+namespace filesystem {
+namespace detail {
+
 //--------------------------------------------------------------------------------------//
 //                                                                                      //
 //                        helpers (all operating systems)                               //
 //                                                                                      //
 //--------------------------------------------------------------------------------------//
 
-namespace
-{
+namespace {
 
-  fs::file_type query_file_type(const path& p, error_code* ec);
+// Absolute maximum path length, in bytes, that we're willing to accept from various system calls.
+// This value is arbitrary, it is supposed to be a hard limit to avoid memory exhaustion
+// in some of the algorithms below in case of some corrupted or maliciously broken filesystem.
+BOOST_CONSTEXPR_OR_CONST std::size_t absolute_path_max = 16u * 1024u * 1024u;
 
-  boost::filesystem::directory_iterator end_dir_itr;
+fs::file_type query_file_type(const path& p, error_code* ec);
 
-  //  error handling helpers  ----------------------------------------------------------//
+//  general helpers  -----------------------------------------------------------------//
 
-  bool error(err_t error_num, error_code* ec, const char* message);
-  bool error(err_t error_num, const path& p, error_code* ec, const char* message);
-  bool error(err_t error_num, const path& p1, const path& p2, error_code* ec,
-    const char* message);
+bool is_empty_directory(const path& p, error_code* ec)
+{
+  return (ec != 0 ? fs::directory_iterator(p, *ec) : fs::directory_iterator(p))
+    == fs::directory_iterator();
+}
 
-  const error_code ok;
+bool not_found_error(int errval) BOOST_NOEXCEPT; // forward declaration
 
-  //  error_num is value of errno on POSIX, error code (from ::GetLastError()) on Windows.
-  //  Interface changed 30 Jan 15 to have caller supply error_num as ::SetLastError()
-  //  values were apparently getting cleared before they could be retrieved by error().
+// only called if directory exists
+bool remove_directory(const path& p) // true if succeeds or not found
+{
+  return BOOST_REMOVE_DIRECTORY(p.c_str())
+    || not_found_error(BOOST_ERRNO);  // mitigate possible file system race. See #11166
+}
 
-  bool error(err_t error_num, error_code* ec, const char* message)
-  {
-    if (!error_num)
-    {
-      if (ec != 0) ec->clear();
-    }
-    else  
-    { //  error
-      if (ec == 0)
-        BOOST_FILESYSTEM_THROW(filesystem_error(message,
-          error_code(error_num, system_category())));
-      else
-        ec->assign(error_num, system_category());
-    }
-    return error_num != 0;
-  }
+// only called if file exists
+bool remove_file(const path& p) // true if succeeds or not found
+{
+  return BOOST_DELETE_FILE(p.c_str())
+    || not_found_error(BOOST_ERRNO);  // mitigate possible file system race. See #11166
+}
 
-  bool error(err_t error_num, const path& p, error_code* ec, const char* message)
+// called by remove and remove_all_aux
+bool remove_file_or_directory(const path& p, fs::file_type type, error_code* ec)
+  // return true if file removed, false if not removed
+{
+  if (type == fs::file_not_found)
   {
-    if (!error_num)
-    {
-      if (ec != 0) ec->clear();
-    }
-    else  
-    { //  error
-      if (ec == 0)
-        BOOST_FILESYSTEM_THROW(filesystem_error(message,
-          p, error_code(error_num, system_category())));
-      else
-        ec->assign(error_num, system_category());
-    }
-    return error_num != 0;
+    if (ec != 0) ec->clear();
+    return false;
   }
 
-  bool error(err_t error_num, const path& p1, const path& p2, error_code* ec,
-    const char* message)
+  if (type == fs::directory_file
+#     ifdef BOOST_WINDOWS_API
+      || type == fs::_detail_directory_symlink
+#     endif
+    )
   {
-    if (!error_num)
-    {
-      if (ec != 0) ec->clear();
-    }
-    else  
-    { //  error
-      if (ec == 0)
-        BOOST_FILESYSTEM_THROW(filesystem_error(message,
-          p1, p2, error_code(error_num, system_category())));
-      else
-        ec->assign(error_num, system_category());
-    }
-    return error_num != 0;
+    if (error(!remove_directory(p) ? BOOST_ERRNO : 0, p, ec,
+      "boost::filesystem::remove"))
+        return false;
   }
-
-  //  general helpers  -----------------------------------------------------------------//
-
-  bool is_empty_directory(const path& p, error_code* ec)
+  else
   {
-    return (ec != 0 ? fs::directory_iterator(p, *ec) : fs::directory_iterator(p))
-      == end_dir_itr;
+    if (error(!remove_file(p) ? BOOST_ERRNO : 0, p, ec,
+      "boost::filesystem::remove"))
+        return false;
   }
+  return true;
+}
 
-  bool not_found_error(int errval); // forward declaration
+boost::uintmax_t remove_all_aux(const path& p, fs::file_type type,
+  error_code* ec)
+{
+  boost::uintmax_t count = 0;
 
-  // only called if directory exists
-  bool remove_directory(const path& p) // true if succeeds or not found
-  { 
-    return BOOST_REMOVE_DIRECTORY(p.c_str())
-      || not_found_error(BOOST_ERRNO);  // mitigate possible file system race. See #11166
-  }
-  
-  // only called if file exists
-  bool remove_file(const path& p) // true if succeeds or not found
-  {
-    return BOOST_DELETE_FILE(p.c_str())
-      || not_found_error(BOOST_ERRNO);  // mitigate possible file system race. See #11166
-  }
-  
-  // called by remove and remove_all_aux
-  bool remove_file_or_directory(const path& p, fs::file_type type, error_code* ec)
-    // return true if file removed, false if not removed
+  if (type == fs::directory_file)  // but not a directory symlink
   {
-    if (type == fs::file_not_found)
-    {
-      if (ec != 0) ec->clear();
-      return false;
-    }
-
-    if (type == fs::directory_file
-#     ifdef BOOST_WINDOWS_API
-        || type == fs::_detail_directory_symlink
-#     endif
-      )
+    fs::directory_iterator itr;
+    if (ec != 0)
     {
-      if (error(!remove_directory(p) ? BOOST_ERRNO : 0, p, ec,
-        "boost::filesystem::remove"))
-          return false;
+      itr = fs::directory_iterator(p, *ec);
+      if (*ec)
+        return count;
     }
     else
+      itr = fs::directory_iterator(p);
+
+    const fs::directory_iterator end_dit;
+    while(itr != end_dit)
     {
-      if (error(!remove_file(p) ? BOOST_ERRNO : 0, p, ec,
-        "boost::filesystem::remove"))
-          return false;
+      fs::file_type tmp_type = query_file_type(itr->path(), ec);
+      if (ec != 0 && *ec)
+        return count;
+
+      count += remove_all_aux(itr->path(), tmp_type, ec);
+      if (ec != 0 && *ec)
+        return count;
+
+      fs::detail::directory_iterator_increment(itr, ec);
+      if (ec != 0 && *ec)
+        return count;
     }
-    return true;
   }
 
-  boost::uintmax_t remove_all_aux(const path& p, fs::file_type type,
-    error_code* ec)
-  {
-    boost::uintmax_t count = 1;
-    if (type == fs::directory_file)  // but not a directory symlink
-    {
-      fs::directory_iterator itr;
-      if (ec != 0)
-      {
-        itr = fs::directory_iterator(p, *ec);
-        if (*ec)
-          return count;
-      }
-      else
-        itr = fs::directory_iterator(p);
-      for (; itr != end_dir_itr; ++itr)
-      {
-        fs::file_type tmp_type = query_file_type(itr->path(), ec);
-        if (ec != 0 && *ec)
-          return count;
-        count += remove_all_aux(itr->path(), tmp_type, ec);
-        if (ec != 0 && *ec)
-          return count;
-      }
-    }
-    remove_file_or_directory(p, type, ec);
+  remove_file_or_directory(p, type, ec);
+  if (ec != 0 && *ec)
     return count;
-  }
+
+  return ++count;
+}
 
 #ifdef BOOST_POSIX_API
 
@@ -417,83 +370,83 @@ namespace
 //                                                                                      //
 //--------------------------------------------------------------------------------------//
 
-  const char dot = '.';
+BOOST_CONSTEXPR_OR_CONST char dot = '.';
 
-  bool not_found_error(int errval)
-  {
-    return errno == ENOENT || errno == ENOTDIR;
-  }
+inline bool not_found_error(int errval) BOOST_NOEXCEPT
+{
+  return errval == ENOENT || errval == ENOTDIR;
+}
 
-  bool // true if ok
-  copy_file_api(const std::string& from_p,
-    const std::string& to_p, bool fail_if_exists)
-  {
-    const std::size_t buf_sz = 32768;
-    boost::scoped_array<char> buf(new char [buf_sz]);
-    int infile=-1, outfile=-1;  // -1 means not open
+bool // true if ok
+copy_file_api(const std::string& from_p,
+  const std::string& to_p, bool fail_if_exists)
+{
+  BOOST_CONSTEXPR_OR_CONST std::size_t buf_sz = 65536;
+  boost::scoped_array<char> buf(new char [buf_sz]);
+  int infile=-1, outfile=-1;  // -1 means not open
 
-    // bug fixed: code previously did a stat()on the from_file first, but that
-    // introduced a gratuitous race condition; the stat()is now done after the open()
+  // bug fixed: code previously did a stat()on the from_file first, but that
+  // introduced a gratuitous race condition; the stat()is now done after the open()
 
-    if ((infile = ::open(from_p.c_str(), O_RDONLY))< 0)
-      { return false; }
+  if ((infile = ::open(from_p.c_str(), O_RDONLY))< 0)
+    { return false; }
 
-    struct stat from_stat;
-    if (::stat(from_p.c_str(), &from_stat)!= 0)
-    { 
-      ::close(infile);
-      return false;
-    }
+  struct stat from_stat;
+  if (::stat(from_p.c_str(), &from_stat)!= 0)
+  {
+    ::close(infile);
+    return false;
+  }
 
-    int oflag = O_CREAT | O_WRONLY | O_TRUNC;
-    if (fail_if_exists)
-      oflag |= O_EXCL;
-    if ((outfile = ::open(to_p.c_str(), oflag, from_stat.st_mode))< 0)
-    {
-      int open_errno = errno;
-      BOOST_ASSERT(infile >= 0);
-      ::close(infile);
-      errno = open_errno;
-      return false;
-    }
+  int oflag = O_CREAT | O_WRONLY | O_TRUNC;
+  if (fail_if_exists)
+    oflag |= O_EXCL;
+  if ((outfile = ::open(to_p.c_str(), oflag, from_stat.st_mode)) < 0)
+  {
+    const int open_errno = errno;
+    BOOST_ASSERT(infile >= 0);
+    ::close(infile);
+    errno = open_errno;
+    return false;
+  }
 
-    ssize_t sz, sz_read=1, sz_write;
-    while (sz_read > 0
-      && (sz_read = ::read(infile, buf.get(), buf_sz)) > 0)
+  ssize_t sz, sz_read=1, sz_write;
+  while (sz_read > 0
+    && (sz_read = ::read(infile, buf.get(), buf_sz)) > 0)
+  {
+    // Allow for partial writes - see Advanced Unix Programming (2nd Ed.),
+    // Marc Rochkind, Addison-Wesley, 2004, page 94
+    sz_write = 0;
+    do
     {
-      // Allow for partial writes - see Advanced Unix Programming (2nd Ed.),
-      // Marc Rochkind, Addison-Wesley, 2004, page 94
-      sz_write = 0;
-      do
+      BOOST_ASSERT(sz_read - sz_write > 0);  // #1
+        // ticket 4438 claimed possible infinite loop if write returns 0. My analysis
+        // is that POSIX specifies 0 return only if 3rd arg is 0, and that will never
+        // happen due to loop entry and coninuation conditions. BOOST_ASSERT #1 above
+        // and #2 below added to verify that analysis.
+      if ((sz = ::write(outfile, buf.get() + sz_write,
+        sz_read - sz_write)) < 0)
       {
-        BOOST_ASSERT(sz_read - sz_write > 0);  // #1
-          // ticket 4438 claimed possible infinite loop if write returns 0. My analysis
-          // is that POSIX specifies 0 return only if 3rd arg is 0, and that will never
-          // happen due to loop entry and coninuation conditions. BOOST_ASSERT #1 above
-          // and #2 below added to verify that analysis.
-        if ((sz = ::write(outfile, buf.get() + sz_write,
-          sz_read - sz_write)) < 0)
-        { 
-          sz_read = sz; // cause read loop termination
-          break;        //  and error reported after closes
-        }
-        BOOST_ASSERT(sz > 0);                  // #2
-        sz_write += sz;
-      } while (sz_write < sz_read);
-    }
+        sz_read = sz; // cause read loop termination
+        break;        //  and error reported after closes
+      }
+      BOOST_ASSERT(sz > 0);                  // #2
+      sz_write += sz;
+    } while (sz_write < sz_read);
+  }
 
-    if (::close(infile)< 0)
-      sz_read = -1;
-    if (::close(outfile)< 0)
-      sz_read = -1;
+  if (::close(infile)< 0)
+    sz_read = -1;
+  if (::close(outfile)< 0)
+    sz_read = -1;
 
-    return sz_read >= 0;
-  }
+  return sz_read >= 0;
+}
 
-  inline fs::file_type query_file_type(const path& p, error_code* ec)
-  {
-    return fs::detail::symlink_status(p, ec).type();
-  }
+inline fs::file_type query_file_type(const path& p, error_code* ec)
+{
+  return fs::detail::symlink_status(p, ec).type();
+}
 
 # else
 
@@ -503,215 +456,204 @@ namespace
 //                                                                                      //
 //--------------------------------------------------------------------------------------//
 
-  const std::size_t buf_size=128;
+BOOST_CONSTEXPR_OR_CONST std::size_t buf_size = 128;
 
-  const wchar_t dot = L'.';
+BOOST_CONSTEXPR_OR_CONST wchar_t dot = L'.';
 
-  bool not_found_error(int errval)
+inline std::wstring wgetenv(const wchar_t* name)
+{
+  // use a separate buffer since C++03 basic_string is not required to be contiguous
+  const DWORD size = ::GetEnvironmentVariableW(name, NULL, 0);
+  if (size > 0)
   {
-    return errval == ERROR_FILE_NOT_FOUND
-      || errval == ERROR_PATH_NOT_FOUND
-      || errval == ERROR_INVALID_NAME  // "tools/jam/src/:sys:stat.h", "//foo"
-      || errval == ERROR_INVALID_DRIVE  // USB card reader with no card inserted
-      || errval == ERROR_NOT_READY  // CD/DVD drive with no disc inserted
-      || errval == ERROR_INVALID_PARAMETER  // ":sys:stat.h"
-      || errval == ERROR_BAD_PATHNAME  // "//nosuch" on Win64
-      || errval == ERROR_BAD_NETPATH;  // "//nosuch" on Win32
+    boost::scoped_array<wchar_t> buf(new wchar_t[size]);
+    if (BOOST_LIKELY(::GetEnvironmentVariableW(name, buf.get(), size) > 0))
+      return std::wstring(buf.get());
   }
 
-  static bool equal_extension( wchar_t const* p, wchar_t const (&x1)[ 5 ], wchar_t const (&x2)[ 5 ] )
-  {
-    return
-      (p[0] == x1[0] || p[0] == x2[0]) &&
-      (p[1] == x1[1] || p[1] == x2[1]) &&
-      (p[2] == x1[2] || p[2] == x2[2]) &&
-      (p[3] == x1[3] || p[3] == x2[3]) &&
-      p[4] == 0;
-  }
+  return std::wstring();
+}
 
-  perms make_permissions(const path& p, DWORD attr)
-  {
-    perms prms = fs::owner_read | fs::group_read | fs::others_read;
-    if  ((attr & FILE_ATTRIBUTE_READONLY) == 0)
-      prms |= fs::owner_write | fs::group_write | fs::others_write;
-    path ext = p.extension();
-    wchar_t const* q = ext.c_str();
-    if (equal_extension(q, L".exe", L".EXE")
-      || equal_extension(q, L".com", L".COM")
-      || equal_extension(q, L".bat", L".BAT")
-      || equal_extension(q, L".cmd", L".CMD"))
-      prms |= fs::owner_exe | fs::group_exe | fs::others_exe;
-    return prms;
-  }
+inline bool not_found_error(int errval) BOOST_NOEXCEPT
+{
+  return errval == ERROR_FILE_NOT_FOUND
+    || errval == ERROR_PATH_NOT_FOUND
+    || errval == ERROR_INVALID_NAME  // "tools/jam/src/:sys:stat.h", "//foo"
+    || errval == ERROR_INVALID_DRIVE  // USB card reader with no card inserted
+    || errval == ERROR_NOT_READY  // CD/DVD drive with no disc inserted
+    || errval == ERROR_INVALID_PARAMETER  // ":sys:stat.h"
+    || errval == ERROR_BAD_PATHNAME  // "//nosuch" on Win64
+    || errval == ERROR_BAD_NETPATH;  // "//nosuch" on Win32
+}
 
-  // these constants come from inspecting some Microsoft sample code
-  std::time_t to_time_t(const FILETIME & ft)
-  {
-    __int64 t = (static_cast<__int64>(ft.dwHighDateTime)<< 32)
-      + ft.dwLowDateTime;
+// these constants come from inspecting some Microsoft sample code
+std::time_t to_time_t(const FILETIME & ft)
+{
+  __int64 t = (static_cast<__int64>(ft.dwHighDateTime)<< 32)
+    + ft.dwLowDateTime;
 #   if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // > VC++ 7.0
-    t -= 116444736000000000LL;
+  t -= 116444736000000000LL;
 #   else
-    t -= 116444736000000000;
+  t -= 116444736000000000;
 #   endif
-    t /= 10000000;
-    return static_cast<std::time_t>(t);
-  }
+  t /= 10000000;
+  return static_cast<std::time_t>(t);
+}
 
-  void to_FILETIME(std::time_t t, FILETIME & ft)
-  {
-    __int64 temp = t;
-    temp *= 10000000;
+void to_FILETIME(std::time_t t, FILETIME & ft)
+{
+  __int64 temp = t;
+  temp *= 10000000;
 #   if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // > VC++ 7.0
-    temp += 116444736000000000LL;
+  temp += 116444736000000000LL;
 #   else
-    temp += 116444736000000000;
+  temp += 116444736000000000;
 #   endif
-    ft.dwLowDateTime = static_cast<DWORD>(temp);
-    ft.dwHighDateTime = static_cast<DWORD>(temp >> 32);
-  }
-
-  // Thanks to Jeremy Maitin-Shepard for much help and for permission to
-  // base the equivalent()implementation on portions of his 
-  // file-equivalence-win32.cpp experimental code.
+  ft.dwLowDateTime = static_cast<DWORD>(temp);
+  ft.dwHighDateTime = static_cast<DWORD>(temp >> 32);
+}
 
-  struct handle_wrapper
-  {
-    HANDLE handle;
-    handle_wrapper(HANDLE h)
-      : handle(h){}
-    ~handle_wrapper()
-    {
-      if (handle != INVALID_HANDLE_VALUE)
-        ::CloseHandle(handle);
-    }
-  };
+// Thanks to Jeremy Maitin-Shepard for much help and for permission to
+// base the equivalent()implementation on portions of his
+// file-equivalence-win32.cpp experimental code.
 
-  HANDLE create_file_handle(const path& p, DWORD dwDesiredAccess,
-    DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
-    DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
-    HANDLE hTemplateFile)
+struct handle_wrapper
+{
+  HANDLE handle;
+  handle_wrapper(HANDLE h)
+    : handle(h){}
+  ~handle_wrapper()
   {
-    return ::CreateFileW(p.c_str(), dwDesiredAccess, dwShareMode,
-      lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
-      hTemplateFile);
+    if (handle != INVALID_HANDLE_VALUE)
+      ::CloseHandle(handle);
   }
+};
 
-  bool is_reparse_point_a_symlink(const path& p)
-  {
-    handle_wrapper h(create_file_handle(p, FILE_READ_EA,
-      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
-      FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL));
-    if (h.handle == INVALID_HANDLE_VALUE)
-      return false;
+HANDLE create_file_handle(const path& p, DWORD dwDesiredAccess,
+  DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+  DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
+  HANDLE hTemplateFile)
+{
+  return ::CreateFileW(p.c_str(), dwDesiredAccess, dwShareMode,
+    lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
+    hTemplateFile);
+}
 
-    boost::scoped_array<char> buf(new char [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);    
-    // Query the reparse data
-    DWORD dwRetLen;
-    BOOL result = ::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buf.get(),
-      MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dwRetLen, NULL);
-    if (!result) return false;
-
-    return reinterpret_cast<const REPARSE_DATA_BUFFER*>(buf.get())->ReparseTag
-        == IO_REPARSE_TAG_SYMLINK
-        // Issue 9016 asked that NTFS directory junctions be recognized as directories.
-        // That is equivalent to recognizing them as symlinks, and then the normal symlink
-        // mechanism will take care of recognizing them as directories.
-        //
-        // Directory junctions are very similar to symlinks, but have some performance
-        // and other advantages over symlinks. They can be created from the command line
-        // with "mklink /j junction-name target-path".
-      || reinterpret_cast<const REPARSE_DATA_BUFFER*>(buf.get())->ReparseTag
-        == IO_REPARSE_TAG_MOUNT_POINT;  // aka "directory junction" or "junction"
-  }
+bool is_reparse_point_a_symlink(const path& p)
+{
+  handle_wrapper h(create_file_handle(p, FILE_READ_EA,
+    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
+    FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL));
+  if (h.handle == INVALID_HANDLE_VALUE)
+    return false;
 
-  inline std::size_t get_full_path_name(
-    const path& src, std::size_t len, wchar_t* buf, wchar_t** p)
+  boost::scoped_array<char> buf(new char [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
+
+  // Query the reparse data
+  DWORD dwRetLen;
+  BOOL result = ::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buf.get(),
+    MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dwRetLen, NULL);
+  if (!result) return false;
+
+  return reinterpret_cast<const REPARSE_DATA_BUFFER*>(buf.get())->ReparseTag
+      == IO_REPARSE_TAG_SYMLINK
+      // Issue 9016 asked that NTFS directory junctions be recognized as directories.
+      // That is equivalent to recognizing them as symlinks, and then the normal symlink
+      // mechanism will take care of recognizing them as directories.
+      //
+      // Directory junctions are very similar to symlinks, but have some performance
+      // and other advantages over symlinks. They can be created from the command line
+      // with "mklink /j junction-name target-path".
+    || reinterpret_cast<const REPARSE_DATA_BUFFER*>(buf.get())->ReparseTag
+      == IO_REPARSE_TAG_MOUNT_POINT;  // aka "directory junction" or "junction"
+}
+
+inline std::size_t get_full_path_name(
+  const path& src, std::size_t len, wchar_t* buf, wchar_t** p)
+{
+  return static_cast<std::size_t>(
+    ::GetFullPathNameW(src.c_str(), static_cast<DWORD>(len), buf, p));
+}
+
+fs::file_status process_status_failure(const path& p, error_code* ec)
+{
+  int errval(::GetLastError());
+  if (ec != 0)                             // always report errval, even though some
+    ec->assign(errval, system_category());   // errval values are not status_errors
+
+  if (not_found_error(errval))
   {
-    return static_cast<std::size_t>(
-      ::GetFullPathNameW(src.c_str(), static_cast<DWORD>(len), buf, p));
+    return fs::file_status(fs::file_not_found, fs::no_perms);
   }
-
-  fs::file_status process_status_failure(const path& p, error_code* ec)
+  else if (errval == ERROR_SHARING_VIOLATION)
   {
-    int errval(::GetLastError());
-    if (ec != 0)                             // always report errval, even though some
-      ec->assign(errval, system_category());   // errval values are not status_errors
-
-    if (not_found_error(errval))
-    {
-      return fs::file_status(fs::file_not_found, fs::no_perms);
-    }
-    else if (errval == ERROR_SHARING_VIOLATION)
-    {
-      return fs::file_status(fs::type_unknown);
-    }
-    if (ec == 0)
-      BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
-        p, error_code(errval, system_category())));
-    return fs::file_status(fs::status_error);
+    return fs::file_status(fs::type_unknown);
   }
+  if (ec == 0)
+    BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
+      p, error_code(errval, system_category())));
+  return fs::file_status(fs::status_error);
+}
 
-  //  differs from symlink_status() in that directory symlinks are reported as
-  //  _detail_directory_symlink, as required on Windows by remove() and its helpers.
-  fs::file_type query_file_type(const path& p, error_code* ec)
+//  differs from symlink_status() in that directory symlinks are reported as
+//  _detail_directory_symlink, as required on Windows by remove() and its helpers.
+fs::file_type query_file_type(const path& p, error_code* ec)
+{
+  DWORD attr(::GetFileAttributesW(p.c_str()));
+  if (attr == 0xFFFFFFFF)
   {
-    DWORD attr(::GetFileAttributesW(p.c_str()));
-    if (attr == 0xFFFFFFFF)
-    {
-      return process_status_failure(p, ec).type();
-    }
-
-    if (ec != 0) ec->clear();
-
-    if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
-    {
-      if (is_reparse_point_a_symlink(p))
-        return (attr & FILE_ATTRIBUTE_DIRECTORY)
-          ? fs::_detail_directory_symlink
-          : fs::symlink_file;
-      return fs::reparse_file;
-    }
-
-    return (attr & FILE_ATTRIBUTE_DIRECTORY)
-      ? fs::directory_file
-      : fs::regular_file;
+    return process_status_failure(p, ec).type();
   }
 
-  BOOL resize_file_api(const wchar_t* p, boost::uintmax_t size)
+  if (ec != 0) ec->clear();
+
+  if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
   {
-    handle_wrapper h(CreateFileW(p, GENERIC_WRITE, 0, 0, OPEN_EXISTING,
-                                FILE_ATTRIBUTE_NORMAL, 0));
-    LARGE_INTEGER sz;
-    sz.QuadPart = size;
-    return h.handle != INVALID_HANDLE_VALUE
-      && ::SetFilePointerEx(h.handle, sz, 0, FILE_BEGIN)
-      && ::SetEndOfFile(h.handle);
+    if (is_reparse_point_a_symlink(p))
+      return (attr & FILE_ATTRIBUTE_DIRECTORY)
+        ? fs::_detail_directory_symlink
+        : fs::symlink_file;
+    return fs::reparse_file;
   }
 
-  //  Windows kernel32.dll functions that may or may not be present
-  //  must be accessed through pointers
+  return (attr & FILE_ATTRIBUTE_DIRECTORY)
+    ? fs::directory_file
+    : fs::regular_file;
+}
+
+BOOL resize_file_api(const wchar_t* p, boost::uintmax_t size)
+{
+  handle_wrapper h(CreateFileW(p, GENERIC_WRITE, 0, 0, OPEN_EXISTING,
+                              FILE_ATTRIBUTE_NORMAL, 0));
+  LARGE_INTEGER sz;
+  sz.QuadPart = size;
+  return h.handle != INVALID_HANDLE_VALUE
+    && ::SetFilePointerEx(h.handle, sz, 0, FILE_BEGIN)
+    && ::SetEndOfFile(h.handle);
+}
+
+//  Windows kernel32.dll functions that may or may not be present
+//  must be accessed through pointers
 
-  typedef BOOL (WINAPI *PtrCreateHardLinkW)(
-    /*__in*/       LPCWSTR lpFileName,
-    /*__in*/       LPCWSTR lpExistingFileName,
-    /*__reserved*/ LPSECURITY_ATTRIBUTES lpSecurityAttributes
  );
+typedef BOOL (WINAPI *PtrCreateHardLinkW)(
+  /*__in*/       LPCWSTR lpFileName,
+  /*__in*/       LPCWSTR lpExistingFileName,
+  /*__reserved*/ LPSECURITY_ATTRIBUTES lpSecurityAttributes
+ );
 
-  PtrCreateHardLinkW create_hard_link_api = PtrCreateHardLinkW(
-    ::GetProcAddress(
-      ::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"));
+PtrCreateHardLinkW create_hard_link_api = PtrCreateHardLinkW(
+  boost::winapi::get_proc_address(
+    boost::winapi::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"));
 
-  typedef BOOLEAN (WINAPI *PtrCreateSymbolicLinkW)(
-    /*__in*/ LPCWSTR lpSymlinkFileName,
-    /*__in*/ LPCWSTR lpTargetFileName,
-    /*__in*/ DWORD dwFlags
  );
+typedef BOOLEAN (WINAPI *PtrCreateSymbolicLinkW)(
+  /*__in*/ LPCWSTR lpSymlinkFileName,
+  /*__in*/ LPCWSTR lpTargetFileName,
+  /*__in*/ DWORD dwFlags
+ );
 
-  PtrCreateSymbolicLinkW create_symbolic_link_api = PtrCreateSymbolicLinkW(
-    ::GetProcAddress(
-      ::GetModuleHandleW(L"kernel32.dll"), "CreateSymbolicLinkW"));
+PtrCreateSymbolicLinkW create_symbolic_link_api = PtrCreateSymbolicLinkW(
+  boost::winapi::get_proc_address(
+    boost::winapi::GetModuleHandleW(L"kernel32.dll"), "CreateSymbolicLinkW"));
 
 #endif
 
@@ -725,6 +667,7 @@ namespace
 //#endif
 
 } // unnamed namespace
+} // namespace detail
 
 //--------------------------------------------------------------------------------------//
 //                                                                                      //
@@ -733,1633 +676,1321 @@ namespace
 //                                                                                      //
 //--------------------------------------------------------------------------------------//
 
-namespace boost
+BOOST_FILESYSTEM_DECL
+path absolute(const path& p, const path& base)
 {
-namespace filesystem
-{
-
-  BOOST_FILESYSTEM_DECL
-  path absolute(const path& p, const path& base)
-  {
-//    if ( p.empty() || p.is_absolute() )
-//      return p;
-//    //  recursively calling absolute is sub-optimal, but is simple
-//    path abs_base(base.is_absolute() ? base : absolute(base));
+//  if ( p.empty() || p.is_absolute() )
+//    return p;
+//  //  recursively calling absolute is sub-optimal, but is simple
+//  path abs_base(base.is_absolute() ? base : absolute(base));
 //# ifdef BOOST_WINDOWS_API
-//    if (p.has_root_directory())
-//      return abs_base.root_name() / p;
-//    //  !p.has_root_directory
-//    if (p.has_root_name())
-//      return p.root_name()
-//        / abs_base.root_directory() / abs_base.relative_path() / p.relative_path();
-//    //  !p.has_root_name()
+//  if (p.has_root_directory())
+//    return abs_base.root_name() / p;
+//  //  !p.has_root_directory
+//  if (p.has_root_name())
+//    return p.root_name()
+//      / abs_base.root_directory() / abs_base.relative_path() / p.relative_path();
+//  //  !p.has_root_name()
 //# endif
-//    return abs_base / p;
-
-    //  recursively calling absolute is sub-optimal, but is sure and simple
-    path abs_base(base.is_absolute() ? base : absolute(base));
-
-    //  store expensive to compute values that are needed multiple times
-    path p_root_name (p.root_name());
-    path base_root_name (abs_base.root_name());
-    path p_root_directory (p.root_directory());
-
-    if (p.empty())
-      return abs_base;
+//  return abs_base / p;
 
-    if (!p_root_name.empty())  // p.has_root_name()
-    {
-      if (p_root_directory.empty())  // !p.has_root_directory()
-        return p_root_name / abs_base.root_directory()
-        / abs_base.relative_path() / p.relative_path();
-      // p is absolute, so fall through to return p at end of block
-    }
+  //  recursively calling absolute is sub-optimal, but is sure and simple
+  path abs_base(base.is_absolute() ? base : absolute(base));
 
-    else if (!p_root_directory.empty())  // p.has_root_directory()
-    {
-#     ifdef BOOST_POSIX_API
-      // POSIX can have root name it it is a network path
-      if (base_root_name.empty())   // !abs_base.has_root_name()
-        return p;
-#     endif
-      return base_root_name / p;
-    }
+  //  store expensive to compute values that are needed multiple times
+  path p_root_name (p.root_name());
+  path base_root_name (abs_base.root_name());
+  path p_root_directory (p.root_directory());
 
-    else
-    {
-      return abs_base / p;
-    }
+  if (p.empty())
+    return abs_base;
 
-    return p;  // p.is_absolute() is true
+  if (!p_root_name.empty())  // p.has_root_name()
+  {
+    if (p_root_directory.empty())  // !p.has_root_directory()
+      return p_root_name / abs_base.root_directory()
+      / abs_base.relative_path() / p.relative_path();
+    // p is absolute, so fall through to return p at end of block
   }
-
-namespace detail
-{
-  BOOST_FILESYSTEM_DECL bool possible_large_file_size_support()
+  else if (!p_root_directory.empty())  // p.has_root_directory()
   {
 #   ifdef BOOST_POSIX_API
-    struct stat lcl_stat;
-    return sizeof(lcl_stat.st_size)> 4;
-#   else
-    return true;
+    // POSIX can have root name it it is a network path
+    if (base_root_name.empty())   // !abs_base.has_root_name()
+      return p;
 #   endif
+    return base_root_name / p;
   }
-
-  BOOST_FILESYSTEM_DECL
-  path canonical(const path& p, const path& base, system::error_code* ec)
+  else
   {
-    path source (p.is_absolute() ? p : absolute(p, base));
-    path root(source.root_path());
-    path result;
+    return abs_base / p;
+  }
 
-    system::error_code local_ec;
-    file_status stat (status(source, local_ec));
+  return p;  // p.is_absolute() is true
+}
 
-    if (stat.type() == fs::file_not_found)
-    {
-      if (ec == 0)
-        BOOST_FILESYSTEM_THROW(filesystem_error(
-          "boost::filesystem::canonical", source,
-          error_code(system::errc::no_such_file_or_directory, system::generic_category())));
-      ec->assign(system::errc::no_such_file_or_directory, system::generic_category());
-      return result;
-    }
-    else if (local_ec)
-    {
-      if (ec == 0)
-        BOOST_FILESYSTEM_THROW(filesystem_error(
-          "boost::filesystem::canonical", source, local_ec));
-      *ec = local_ec;
-      return result;
-    }
+namespace detail {
+
+BOOST_FILESYSTEM_DECL bool possible_large_file_size_support()
+{
+# ifdef BOOST_POSIX_API
+  typedef struct stat struct_stat;
+  return sizeof(struct_stat().st_size) > 4;
+# else
+  return true;
+# endif
+}
+
+BOOST_FILESYSTEM_DECL
+path canonical(const path& p, const path& base, system::error_code* ec)
+{
+  path source (p.is_absolute() ? p : absolute(p, base));
+  path root(source.root_path());
+  path result;
+
+  system::error_code local_ec;
+  file_status stat (status(source, local_ec));
+
+  if (stat.type() == fs::file_not_found)
+  {
+    if (ec == 0)
+      BOOST_FILESYSTEM_THROW(filesystem_error(
+        "boost::filesystem::canonical", source,
+        error_code(system::errc::no_such_file_or_directory, system::generic_category())));
+    ec->assign(system::errc::no_such_file_or_directory, system::generic_category());
+    return result;
+  }
+  else if (local_ec)
+  {
+    if (ec == 0)
+      BOOST_FILESYSTEM_THROW(filesystem_error(
+        "boost::filesystem::canonical", source, local_ec));
+    *ec = local_ec;
+    return result;
+  }
 
-    bool scan (true);
-    while (scan)
+  bool scan = true;
+  while (scan)
+  {
+    scan = false;
+    result.clear();
+    for (path::iterator itr = source.begin(); itr != source.end(); ++itr)
     {
-      scan = false;
-      result.clear();
-      for (path::iterator itr = source.begin(); itr != source.end(); ++itr)
+      if (*itr == dot_path())
+        continue;
+      if (*itr == dot_dot_path())
       {
-        if (*itr == dot_path())
-          continue;
-        if (*itr == dot_dot_path())
-        {
-          if (result != root)
-            result.remove_filename();
-          continue;
-        }
+        if (result != root)
+          result.remove_filename();
+        continue;
+      }
+
+      result /= *itr;
 
-        result /= *itr;
+      bool is_sym (is_symlink(detail::symlink_status(result, ec)));
+      if (ec && *ec)
+        return path();
 
-        bool is_sym (is_symlink(detail::symlink_status(result, ec)));
+      if (is_sym)
+      {
+        path link(detail::read_symlink(result, ec));
         if (ec && *ec)
           return path();
+        result.remove_filename();
 
-        if (is_sym)
+        if (link.is_absolute())
         {
-          path link(detail::read_symlink(result, ec));
-          if (ec && *ec)
-            return path();
-          result.remove_filename();
-
-          if (link.is_absolute())
-          {
-            for (++itr; itr != source.end(); ++itr)
-              link /= *itr;
-            source = link;
-          }
-          else // link is relative
-          {
-            path new_source(result);
-            new_source /= link;
-            for (++itr; itr != source.end(); ++itr)
-              new_source /= *itr;
-            source = new_source;
-          }
-          scan = true;  // symlink causes scan to be restarted
-          break;
+          for (++itr; itr != source.end(); ++itr)
+            link /= *itr;
+          source = link;
         }
+        else // link is relative
+        {
+          path new_source(result);
+          new_source /= link;
+          for (++itr; itr != source.end(); ++itr)
+            new_source /= *itr;
+          source = new_source;
+        }
+        scan = true;  // symlink causes scan to be restarted
+        break;
       }
     }
-    if (ec != 0)
-      ec->clear();
-    BOOST_ASSERT_MSG(result.is_absolute(), "canonical() implementation error; please report");
-    return result;
   }
+  if (ec != 0)
+    ec->clear();
+  BOOST_ASSERT_MSG(result.is_absolute(), "canonical() implementation error; please report");
+  return result;
+}
 
-  BOOST_FILESYSTEM_DECL
-  void copy(const path& from, const path& to, system::error_code* ec)
-  {
-    file_status s(symlink_status(from, *ec));
-    if (ec != 0 && *ec) return;
+BOOST_FILESYSTEM_DECL
+void copy(const path& from, const path& to, system::error_code* ec)
+{
+  file_status s(detail::symlink_status(from, ec));
+  if (ec != 0 && *ec) return;
 
-    if(is_symlink(s))
-    {
-      copy_symlink(from, to, *ec);
-    }
-    else if(is_directory(s))
-    {
-      copy_directory(from, to, *ec);
-    }
-    else if(is_regular_file(s))
-    {
-      copy_file(from, to, fs::copy_option::fail_if_exists, *ec);
-    }
-    else
-    {
-      if (ec == 0)
-        BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::copy",
-          from, to, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category())));
-      ec->assign(BOOST_ERROR_NOT_SUPPORTED, system_category());
-    }
+  if(is_symlink(s))
+  {
+    detail::copy_symlink(from, to, ec);
   }
-
-  BOOST_FILESYSTEM_DECL
-  void copy_directory(const path& from, const path& to, system::error_code* ec)
+  else if(is_directory(s))
   {
-#   ifdef BOOST_POSIX_API
-    struct stat from_stat;
-#   endif
-    error(!BOOST_COPY_DIRECTORY(from.c_str(), to.c_str()) ? BOOST_ERRNO : 0,
-      from, to, ec, "boost::filesystem::copy_directory");
+    detail::copy_directory(from, to, ec);
   }
-
-  BOOST_FILESYSTEM_DECL
-  void copy_file(const path& from, const path& to, copy_option option, error_code* ec)
+  else if(is_regular_file(s))
   {
-    error(!BOOST_COPY_FILE(from.c_str(), to.c_str(),
-      option == fail_if_exists) ? BOOST_ERRNO : 0,
-        from, to, ec, "boost::filesystem::copy_file");
+    detail::copy_file(from, to, detail::fail_if_exists, ec);
   }
-
-  BOOST_FILESYSTEM_DECL
-  void copy_symlink(const path& existing_symlink, const path& new_symlink,
-    system::error_code* ec)
+  else
   {
+    if (ec == 0)
+      BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::copy",
+        from, to, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category())));
+    ec->assign(BOOST_ERROR_NOT_SUPPORTED, system_category());
+  }
+}
+
+BOOST_FILESYSTEM_DECL
+void copy_directory(const path& from, const path& to, system::error_code* ec)
+{
+# ifdef BOOST_POSIX_API
+  struct stat from_stat;
+# endif
+  error(!BOOST_COPY_DIRECTORY(from.c_str(), to.c_str()) ? BOOST_ERRNO : 0,
+    from, to, ec, "boost::filesystem::copy_directory");
+}
+
+BOOST_FILESYSTEM_DECL
+void copy_file(const path& from, const path& to, copy_option option, error_code* ec)
+{
+  error(!BOOST_COPY_FILE(from.c_str(), to.c_str(),
+    option == fail_if_exists) ? BOOST_ERRNO : 0,
+      from, to, ec, "boost::filesystem::copy_file");
+}
+
+BOOST_FILESYSTEM_DECL
+void copy_symlink(const path& existing_symlink, const path& new_symlink,
+  system::error_code* ec)
+{
 # if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
-    error(BOOST_ERROR_NOT_SUPPORTED, new_symlink, existing_symlink, ec,
-      "boost::filesystem::copy_symlink");
+  error(BOOST_ERROR_NOT_SUPPORTED, new_symlink, existing_symlink, ec,
+    "boost::filesystem::copy_symlink");
 
-# else  // modern Windows or BOOST_POSIX_API 
-    path p(read_symlink(existing_symlink, ec));
-    if (ec != 0 && *ec) return;
-    create_symlink(p, new_symlink, ec);
+# else  // modern Windows or BOOST_POSIX_API
+  path p(read_symlink(existing_symlink, ec));
+  if (ec != 0 && *ec) return;
+  create_symlink(p, new_symlink, ec);
 
 # endif
-  }
+}
 
- BOOST_FILESYSTEM_DECL
-  bool create_directories(const path& p, system::error_code* ec)
-  {
-   if (p.empty())
-   {
-     if (ec == 0)
-       BOOST_FILESYSTEM_THROW(filesystem_error(
-         "boost::filesystem::create_directories", p,
-         system::errc::make_error_code(system::errc::invalid_argument)));
-     else
-       ec->assign(system::errc::invalid_argument, system::generic_category());
-     return false;
-   }
-
-    if (p.filename_is_dot() || p.filename_is_dot_dot())
-      return create_directories(p.parent_path(), ec);
-    
-    error_code local_ec;
-    file_status p_status = status(p, local_ec);
-
-    if (p_status.type() == directory_file)
-    {
-      if (ec != 0)
-        ec->clear();
-      return false;
-    }
+BOOST_FILESYSTEM_DECL
+bool create_directories(const path& p, system::error_code* ec)
+{
+ if (p.empty())
+ {
+   if (ec == 0)
+     BOOST_FILESYSTEM_THROW(filesystem_error(
+       "boost::filesystem::create_directories", p,
+       system::errc::make_error_code(system::errc::invalid_argument)));
+   else
+     ec->assign(system::errc::invalid_argument, system::generic_category());
+   return false;
+ }
 
-    path parent = p.parent_path();
-    BOOST_ASSERT_MSG(parent != p, "internal error: p == p.parent_path()");
-    if (!parent.empty())
-    {
-      // determine if the parent exists
-      file_status parent_status = status(parent, local_ec);
+  if (p.filename_is_dot() || p.filename_is_dot_dot())
+    return create_directories(p.parent_path(), ec);
 
-      // if the parent does not exist, create the parent
-      if (parent_status.type() == file_not_found)
-      {
-        create_directories(parent, local_ec);
-        if (local_ec)
-        {
-          if (ec == 0)
-            BOOST_FILESYSTEM_THROW(filesystem_error(
-              "boost::filesystem::create_directories", parent, local_ec));
-          else
-            *ec = local_ec;
-          return false;
-        }
-      }
-    }
+  error_code local_ec;
+  file_status p_status = status(p, local_ec);
 
-    // create the directory
-    return create_directory(p, ec);
+  if (p_status.type() == directory_file)
+  {
+    if (ec != 0)
+      ec->clear();
+    return false;
   }
 
-  BOOST_FILESYSTEM_DECL
-  bool create_directory(const path& p, error_code* ec)
+  path parent = p.parent_path();
+  BOOST_ASSERT_MSG(parent != p, "internal error: p == p.parent_path()");
+  if (!parent.empty())
   {
-    if (BOOST_CREATE_DIRECTORY(p.c_str()))
+    // determine if the parent exists
+    file_status parent_status = status(parent, local_ec);
+
+    // if the parent does not exist, create the parent
+    if (parent_status.type() == file_not_found)
     {
-      if (ec != 0)
-        ec->clear();
-      return true;
+      create_directories(parent, local_ec);
+      if (local_ec)
+      {
+        if (ec == 0)
+          BOOST_FILESYSTEM_THROW(filesystem_error(
+            "boost::filesystem::create_directories", parent, local_ec));
+        else
+          *ec = local_ec;
+        return false;
+      }
     }
+  }
 
-    //  attempt to create directory failed
-    int errval(BOOST_ERRNO);  // save reason for failure
-    error_code dummy;
+  // create the directory
+  return create_directory(p, ec);
+}
 
-    if (is_directory(p, dummy))
-    {
-      if (ec != 0)
-        ec->clear();
-      return false;
-    }
+BOOST_FILESYSTEM_DECL
+bool create_directory(const path& p, error_code* ec)
+{
+  if (BOOST_CREATE_DIRECTORY(p.c_str()))
+  {
+    if (ec != 0)
+      ec->clear();
+    return true;
+  }
 
-    //  attempt to create directory failed && it doesn't already exist
-    if (ec == 0)
-      BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::create_directory",
-        p, error_code(errval, system_category())));
-    else
-      ec->assign(errval, system_category());
+  //  attempt to create directory failed
+  int errval(BOOST_ERRNO);  // save reason for failure
+  error_code dummy;
 
+  if (is_directory(p, dummy))
+  {
+    if (ec != 0)
+      ec->clear();
     return false;
   }
 
-  BOOST_FILESYSTEM_DECL
-  void create_directory_symlink(const path& to, const path& from,
-                                 system::error_code* ec)
-  {
-#   if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0600  // SDK earlier than Vista and Server 2008
+  //  attempt to create directory failed && it doesn't already exist
+  if (ec == 0)
+    BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::create_directory",
+      p, error_code(errval, system_category())));
+  else
+    ec->assign(errval, system_category());
 
-    error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec,
-      "boost::filesystem::create_directory_symlink");
-#   else
+  return false;
+}
 
-#     if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0600
-        // see if actually supported by Windows runtime dll
-        if (error(!create_symbolic_link_api ? BOOST_ERROR_NOT_SUPPORTED : 0, to, from, ec,
-            "boost::filesystem::create_directory_symlink"))
-          return;
-#     endif
+BOOST_FILESYSTEM_DECL
+void create_directory_symlink(const path& to, const path& from,
+                               system::error_code* ec)
+{
+# if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0600  // SDK earlier than Vista and Server 2008
 
-    error(!BOOST_CREATE_SYMBOLIC_LINK(from.c_str(), to.c_str(),
-      SYMBOLIC_LINK_FLAG_DIRECTORY) ? BOOST_ERRNO : 0,
-      to, from, ec, "boost::filesystem::create_directory_symlink");
-#   endif
-  }
+  error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec,
+    "boost::filesystem::create_directory_symlink");
+# else
 
-  BOOST_FILESYSTEM_DECL
-  void create_hard_link(const path& to, const path& from, error_code* ec)
-  {
+#   if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0600
+      // see if actually supported by Windows runtime dll
+      if (error(!create_symbolic_link_api ? BOOST_ERROR_NOT_SUPPORTED : 0, to, from, ec,
+          "boost::filesystem::create_directory_symlink"))
+        return;
+#   endif
 
-#   if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0500  // SDK earlier than Win 2K
+  error(!BOOST_CREATE_SYMBOLIC_LINK(from.c_str(), to.c_str(),
+    SYMBOLIC_LINK_FLAG_DIRECTORY) ? BOOST_ERRNO : 0,
+    to, from, ec, "boost::filesystem::create_directory_symlink");
+# endif
+}
 
-    error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec,
-      "boost::filesystem::create_hard_link");
-#   else
+BOOST_FILESYSTEM_DECL
+void create_hard_link(const path& to, const path& from, error_code* ec)
+{
+# if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0500  // SDK earlier than Win 2K
 
-#     if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0500
-        // see if actually supported by Windows runtime dll
-        if (error(!create_hard_link_api ? BOOST_ERROR_NOT_SUPPORTED : 0, to, from, ec,
-            "boost::filesystem::create_hard_link"))
-          return;
-#     endif
+  error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec,
+    "boost::filesystem::create_hard_link");
+# else
 
-    error(!BOOST_CREATE_HARD_LINK(from.c_str(), to.c_str()) ? BOOST_ERRNO : 0, to, from, ec,
-      "boost::filesystem::create_hard_link");
+#   if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0500
+      // see if actually supported by Windows runtime dll
+      if (error(!create_hard_link_api ? BOOST_ERROR_NOT_SUPPORTED : 0, to, from, ec,
+          "boost::filesystem::create_hard_link"))
+        return;
 #   endif
-  }
 
-  BOOST_FILESYSTEM_DECL
-  void create_symlink(const path& to, const path& from, error_code* ec)
-  {
-#   if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0600  // SDK earlier than Vista and Server 2008
-    error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec,
-      "boost::filesystem::create_directory_symlink");
-#   else
+  error(!BOOST_CREATE_HARD_LINK(from.c_str(), to.c_str()) ? BOOST_ERRNO : 0, to, from, ec,
+    "boost::filesystem::create_hard_link");
+# endif
+}
 
-#     if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0600
-        // see if actually supported by Windows runtime dll
-        if (error(!create_symbolic_link_api ? BOOST_ERROR_NOT_SUPPORTED : 0, to, from, ec,
-            "boost::filesystem::create_symlink"))
-          return;
-#     endif
+BOOST_FILESYSTEM_DECL
+void create_symlink(const path& to, const path& from, error_code* ec)
+{
+# if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0600  // SDK earlier than Vista and Server 2008
+  error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec,
+    "boost::filesystem::create_directory_symlink");
+# else
 
-    error(!BOOST_CREATE_SYMBOLIC_LINK(from.c_str(), to.c_str(), 0) ? BOOST_ERRNO : 0,
-      to, from, ec, "boost::filesystem::create_symlink");
+#   if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0600
+      // see if actually supported by Windows runtime dll
+      if (error(!create_symbolic_link_api ? BOOST_ERROR_NOT_SUPPORTED : 0, to, from, ec,
+          "boost::filesystem::create_symlink"))
+        return;
 #   endif
-  }
 
-  BOOST_FILESYSTEM_DECL
-  path current_path(error_code* ec)
+  error(!BOOST_CREATE_SYMBOLIC_LINK(from.c_str(), to.c_str(), 0) ? BOOST_ERRNO : 0,
+    to, from, ec, "boost::filesystem::create_symlink");
+# endif
+}
+
+BOOST_FILESYSTEM_DECL
+path current_path(error_code* ec)
+{
+# ifdef BOOST_POSIX_API
+  struct local
+  {
+    static bool getcwd_error(error_code* ec)
+    {
+      const int err = errno;
+      return error((err != ERANGE
+          // bug in some versions of the Metrowerks C lib on the Mac: wrong errno set
+#   if defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
+          && err != 0
+#   endif
+        ) ? err : 0, ec, "boost::filesystem::current_path");
+    }
+  };
+
+  path cur;
+  char small_buf[1024];
+  const char* p = ::getcwd(small_buf, sizeof(small_buf));
+  if (BOOST_LIKELY(!!p))
   {
-#   ifdef BOOST_POSIX_API
-    path cur;
-    for (long path_max = 128;; path_max *=2)// loop 'til buffer large enough
+    cur = p;
+    if (ec != 0) ec->clear();
+  }
+  else if (BOOST_LIKELY(!local::getcwd_error(ec)))
+  {
+    for (std::size_t path_max = sizeof(small_buf);; path_max *= 2u) // loop 'til buffer large enough
     {
-      boost::scoped_array<char>
-        buf(new char[static_cast<std::size_t>(path_max)]);
-      if (::getcwd(buf.get(), static_cast<std::size_t>(path_max))== 0)
+      if (BOOST_UNLIKELY(path_max > absolute_path_max))
       {
-        if (error(errno != ERANGE ? errno : 0
-      // bug in some versions of the Metrowerks C lib on the Mac: wrong errno set 
-#         if defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
-          && errno != 0
-#         endif
-          , ec, "boost::filesystem::current_path"))
-        {
-          break;
-        }
+        if (ec == 0)
+          BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::current_path",
+            error_code(ENAMETOOLONG, system_category())));
+        else
+          ec->assign(ENAMETOOLONG, system_category());
+        break;
       }
-      else
+
+      boost::scoped_array<char> buf(new char[path_max]);
+      p = ::getcwd(buf.get(), path_max);
+      if (BOOST_LIKELY(!!p))
       {
         cur = buf.get();
-        if (ec != 0) ec->clear();
+        if (ec != 0)
+          ec->clear();
+        break;
+      }
+      else if (BOOST_UNLIKELY(local::getcwd_error(ec)))
+      {
         break;
       }
     }
-    return cur;
-
-#   else
-    DWORD sz;
-    if ((sz = ::GetCurrentDirectoryW(0, NULL)) == 0)sz = 1;
-    boost::scoped_array<path::value_type> buf(new path::value_type[sz]);
-    error(::GetCurrentDirectoryW(sz, buf.get()) == 0 ? BOOST_ERRNO : 0, ec,
-      "boost::filesystem::current_path");
-    return path(buf.get());
-#   endif
   }
 
+  return cur;
 
-  BOOST_FILESYSTEM_DECL
-  void current_path(const path& p, system::error_code* ec)
-  {
-    error(!BOOST_SET_CURRENT_DIRECTORY(p.c_str()) ? BOOST_ERRNO : 0,
-      p, ec, "boost::filesystem::current_path");
-  }
+# elif defined(UNDER_CE)
+  // Windows CE has no current directory, so everything's relative to the root of the directory tree
+  return L"\\";
+# else
+  DWORD sz;
+  if ((sz = ::GetCurrentDirectoryW(0, NULL)) == 0)sz = 1;
+  boost::scoped_array<path::value_type> buf(new path::value_type[sz]);
+  error(::GetCurrentDirectoryW(sz, buf.get()) == 0 ? BOOST_ERRNO : 0, ec,
+    "boost::filesystem::current_path");
+  return path(buf.get());
+# endif
+}
 
-  BOOST_FILESYSTEM_DECL
-  bool equivalent(const path& p1, const path& p2, system::error_code* ec)
-  {
-#   ifdef BOOST_POSIX_API
-    struct stat s2;
-    int e2(::stat(p2.c_str(), &s2));
-    struct stat s1;
-    int e1(::stat(p1.c_str(), &s1));
 
-    if (e1 != 0 || e2 != 0)
-    {
-      // if one is invalid and the other isn't then they aren't equivalent,
-      // but if both are invalid then it is an error
-      error (e1 != 0 && e2 != 0, p1, p2, ec, "boost::filesystem::equivalent");
-      return false;
-    }
+BOOST_FILESYSTEM_DECL
+void current_path(const path& p, system::error_code* ec)
+{
+# ifdef UNDER_CE
+  error(BOOST_ERROR_NOT_SUPPORTED, p, ec,
+    "boost::filesystem::current_path");
+# else
+  error(!BOOST_SET_CURRENT_DIRECTORY(p.c_str()) ? BOOST_ERRNO : 0,
+    p, ec, "boost::filesystem::current_path");
+# endif
+}
 
-    // both stats now known to be valid
-    return  s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino
-        // According to the POSIX stat specs, "The st_ino and st_dev fields
-        // taken together uniquely identify the file within the system."
-        // Just to be sure, size and mod time are also checked.
-        && s1.st_size == s2.st_size && s1.st_mtime == s2.st_mtime;
+BOOST_FILESYSTEM_DECL
+bool equivalent(const path& p1, const path& p2, system::error_code* ec)
+{
+# ifdef BOOST_POSIX_API
+  struct stat s2;
+  int e2(::stat(p2.c_str(), &s2));
+  struct stat s1;
+  int e1(::stat(p1.c_str(), &s1));
 
-#   else  // Windows
+  if (e1 != 0 || e2 != 0)
+  {
+    // if one is invalid and the other isn't then they aren't equivalent,
+    // but if both are invalid then it is an error
+    error (e1 != 0 && e2 != 0, p1, p2, ec, "boost::filesystem::equivalent");
+    return false;
+  }
 
-    // Note well: Physical location on external media is part of the
-    // equivalence criteria. If there are no open handles, physical location
-    // can change due to defragmentation or other relocations. Thus handles
-    // must be held open until location information for both paths has
-    // been retrieved.
+  // both stats now known to be valid
+  return  s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino
+      // According to the POSIX stat specs, "The st_ino and st_dev fields
+      // taken together uniquely identify the file within the system."
+      // Just to be sure, size and mod time are also checked.
+      && s1.st_size == s2.st_size && s1.st_mtime == s2.st_mtime;
 
-    // p2 is done first, so any error reported is for p1
-    handle_wrapper h2(
-      create_file_handle(
-          p2.c_str(),
-          0,
-          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
-          0,
-          OPEN_EXISTING,
-          FILE_FLAG_BACKUP_SEMANTICS,
-          0));
+# else  // Windows
 
-    handle_wrapper h1(
-      create_file_handle(
-          p1.c_str(),
-          0,
-          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
-          0,
-          OPEN_EXISTING,
-          FILE_FLAG_BACKUP_SEMANTICS,
-          0));
+  // Note well: Physical location on external media is part of the
+  // equivalence criteria. If there are no open handles, physical location
+  // can change due to defragmentation or other relocations. Thus handles
+  // must be held open until location information for both paths has
+  // been retrieved.
+
+  // p2 is done first, so any error reported is for p1
+  handle_wrapper h2(
+    create_file_handle(
+        p2.c_str(),
+        0,
+        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+        0,
+        OPEN_EXISTING,
+        FILE_FLAG_BACKUP_SEMANTICS,
+        0));
+
+  handle_wrapper h1(
+    create_file_handle(
+        p1.c_str(),
+        0,
+        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+        0,
+        OPEN_EXISTING,
+        FILE_FLAG_BACKUP_SEMANTICS,
+        0));
+
+  if (h1.handle == INVALID_HANDLE_VALUE
+    || h2.handle == INVALID_HANDLE_VALUE)
+  {
+    // if one is invalid and the other isn't, then they aren't equivalent,
+    // but if both are invalid then it is an error
+    error((h1.handle == INVALID_HANDLE_VALUE
+      && h2.handle == INVALID_HANDLE_VALUE) ? BOOST_ERROR_NOT_SUPPORTED : 0, p1, p2, ec,
+        "boost::filesystem::equivalent");
+    return false;
+  }
 
-    if (h1.handle == INVALID_HANDLE_VALUE
-      || h2.handle == INVALID_HANDLE_VALUE)
-    {
-      // if one is invalid and the other isn't, then they aren't equivalent,
-      // but if both are invalid then it is an error
-      error((h1.handle == INVALID_HANDLE_VALUE
-        && h2.handle == INVALID_HANDLE_VALUE) ? BOOST_ERROR_NOT_SUPPORTED : 0, p1, p2, ec,
-          "boost::filesystem::equivalent");
-      return false;
-    }
+  // at this point, both handles are known to be valid
 
-    // at this point, both handles are known to be valid
+  BY_HANDLE_FILE_INFORMATION info1, info2;
 
-    BY_HANDLE_FILE_INFORMATION info1, info2;
+  if (error(!::GetFileInformationByHandle(h1.handle, &info1) ? BOOST_ERRNO : 0,
+    p1, p2, ec, "boost::filesystem::equivalent"))
+    return  false;
 
-    if (error(!::GetFileInformationByHandle(h1.handle, &info1) ? BOOST_ERRNO : 0,
-      p1, p2, ec, "boost::filesystem::equivalent"))
-        return  false;
+  if (error(!::GetFileInformationByHandle(h2.handle, &info2) ? BOOST_ERRNO : 0,
+    p1, p2, ec, "boost::filesystem::equivalent"))
+    return  false;
 
-    if (error(!::GetFileInformationByHandle(h2.handle, &info2) ? BOOST_ERRNO : 0,
-      p1, p2, ec, "boost::filesystem::equivalent"))
-        return  false;
+  // In theory, volume serial numbers are sufficient to distinguish between
+  // devices, but in practice VSN's are sometimes duplicated, so last write
+  // time and file size are also checked.
+  return
+    info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
+    && info1.nFileIndexHigh == info2.nFileIndexHigh
+    && info1.nFileIndexLow == info2.nFileIndexLow
+    && info1.nFileSizeHigh == info2.nFileSizeHigh
+    && info1.nFileSizeLow == info2.nFileSizeLow
+    && info1.ftLastWriteTime.dwLowDateTime
+      == info2.ftLastWriteTime.dwLowDateTime
+    && info1.ftLastWriteTime.dwHighDateTime
+      == info2.ftLastWriteTime.dwHighDateTime;
 
-    // In theory, volume serial numbers are sufficient to distinguish between
-    // devices, but in practice VSN's are sometimes duplicated, so last write
-    // time and file size are also checked.
-      return 
-        info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
-        && info1.nFileIndexHigh == info2.nFileIndexHigh
-        && info1.nFileIndexLow == info2.nFileIndexLow
-        && info1.nFileSizeHigh == info2.nFileSizeHigh
-        && info1.nFileSizeLow == info2.nFileSizeLow
-        && info1.ftLastWriteTime.dwLowDateTime
-          == info2.ftLastWriteTime.dwLowDateTime
-        && info1.ftLastWriteTime.dwHighDateTime
-          == info2.ftLastWriteTime.dwHighDateTime;
+# endif
+}
 
-#   endif
-  }
+BOOST_FILESYSTEM_DECL
+boost::uintmax_t file_size(const path& p, error_code* ec)
+{
+# ifdef BOOST_POSIX_API
 
-  BOOST_FILESYSTEM_DECL
-  boost::uintmax_t file_size(const path& p, error_code* ec)
-  {
-#   ifdef BOOST_POSIX_API
+  struct stat path_stat;
+  if (error(::stat(p.c_str(), &path_stat)!= 0 ? BOOST_ERRNO : 0,
+      p, ec, "boost::filesystem::file_size"))
+    return static_cast<boost::uintmax_t>(-1);
+  if (error(!S_ISREG(path_stat.st_mode) ? EPERM : 0,
+      p, ec, "boost::filesystem::file_size"))
+    return static_cast<boost::uintmax_t>(-1);
 
-    struct stat path_stat;
-    if (error(::stat(p.c_str(), &path_stat)!= 0 ? BOOST_ERRNO : 0,
-        p, ec, "boost::filesystem::file_size"))
-      return static_cast<boost::uintmax_t>(-1);
-   if (error(!S_ISREG(path_stat.st_mode) ? EPERM : 0,
-        p, ec, "boost::filesystem::file_size"))
-      return static_cast<boost::uintmax_t>(-1);
+  return static_cast<boost::uintmax_t>(path_stat.st_size);
 
-    return static_cast<boost::uintmax_t>(path_stat.st_size);
+# else  // Windows
 
-#   else  // Windows
+  // assume uintmax_t is 64-bits on all Windows compilers
 
-    // assume uintmax_t is 64-bits on all Windows compilers
+  WIN32_FILE_ATTRIBUTE_DATA fad;
 
-    WIN32_FILE_ATTRIBUTE_DATA fad;
+  if (error(::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad)== 0
+    ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::file_size"))
+        return static_cast<boost::uintmax_t>(-1);
 
-    if (error(::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad)== 0
-      ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::file_size"))
-          return static_cast<boost::uintmax_t>(-1);
+  if (error((fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!= 0
+    ? ERROR_NOT_SUPPORTED : 0, p, ec, "boost::filesystem::file_size"))
+    return static_cast<boost::uintmax_t>(-1);
 
-    if (error((fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!= 0
-      ? ERROR_NOT_SUPPORTED : 0, p, ec, "boost::filesystem::file_size"))
-      return static_cast<boost::uintmax_t>(-1);
+  return (static_cast<boost::uintmax_t>(fad.nFileSizeHigh)
+            << (sizeof(fad.nFileSizeLow)*8)) + fad.nFileSizeLow;
+# endif
+}
 
-    return (static_cast<boost::uintmax_t>(fad.nFileSizeHigh)
-              << (sizeof(fad.nFileSizeLow)*8)) + fad.nFileSizeLow;
-#   endif
-  }
+BOOST_FILESYSTEM_DECL
+boost::uintmax_t hard_link_count(const path& p, system::error_code* ec)
+{
+# ifdef BOOST_POSIX_API
 
-  BOOST_FILESYSTEM_DECL
-  boost::uintmax_t hard_link_count(const path& p, system::error_code* ec)
-  {
-#   ifdef BOOST_POSIX_API
+  struct stat path_stat;
+  return error(::stat(p.c_str(), &path_stat)!= 0 ? BOOST_ERRNO : 0,
+                p, ec, "boost::filesystem::hard_link_count")
+         ? 0
+         : static_cast<boost::uintmax_t>(path_stat.st_nlink);
 
-    struct stat path_stat;
-    return error(::stat(p.c_str(), &path_stat)!= 0 ? BOOST_ERRNO : 0,
-                  p, ec, "boost::filesystem::hard_link_count")
-           ? 0
-           : static_cast<boost::uintmax_t>(path_stat.st_nlink);
+# else // Windows
 
-#   else // Windows
+  // Link count info is only available through GetFileInformationByHandle
+  BY_HANDLE_FILE_INFORMATION info;
+  handle_wrapper h(
+    create_file_handle(p.c_str(), 0,
+        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
+        OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
+  return
+    !error(h.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0,
+            p, ec, "boost::filesystem::hard_link_count")
+    && !error(::GetFileInformationByHandle(h.handle, &info)== 0 ? BOOST_ERRNO : 0,
+               p, ec, "boost::filesystem::hard_link_count")
+         ? info.nNumberOfLinks
+         : 0;
+# endif
+}
 
-    // Link count info is only available through GetFileInformationByHandle
-    BY_HANDLE_FILE_INFORMATION info;
-    handle_wrapper h(
-      create_file_handle(p.c_str(), 0,
-          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
-          OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
-    return
-      !error(h.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0,
-              p, ec, "boost::filesystem::hard_link_count")
-      && !error(::GetFileInformationByHandle(h.handle, &info)== 0 ? BOOST_ERRNO : 0,
-                 p, ec, "boost::filesystem::hard_link_count")
-           ? info.nNumberOfLinks
-           : 0;
-#   endif
-  }
+BOOST_FILESYSTEM_DECL
+path initial_path(error_code* ec)
+{
+  static path init_path;
+  if (init_path.empty())
+    init_path = current_path(ec);
+  else if (ec != 0) ec->clear();
+  return init_path;
+}
 
-  BOOST_FILESYSTEM_DECL
-  path initial_path(error_code* ec)
-  {
-      static path init_path;
-      if (init_path.empty())
-        init_path = current_path(ec);
-      else if (ec != 0) ec->clear();
-      return init_path;
-  }
+BOOST_FILESYSTEM_DECL
+bool is_empty(const path& p, system::error_code* ec)
+{
+# ifdef BOOST_POSIX_API
 
-  BOOST_FILESYSTEM_DECL
-  bool is_empty(const path& p, system::error_code* ec)
-  {
-#   ifdef BOOST_POSIX_API
+  struct stat path_stat;
+  if (error(::stat(p.c_str(), &path_stat)!= 0,
+      p, ec, "boost::filesystem::is_empty"))
+    return false;
+  return S_ISDIR(path_stat.st_mode)
+    ? is_empty_directory(p, ec)
+    : path_stat.st_size == 0;
 
-    struct stat path_stat;
-    if (error(::stat(p.c_str(), &path_stat)!= 0,
-        p, ec, "boost::filesystem::is_empty"))
-      return false;        
-    return S_ISDIR(path_stat.st_mode)
-      ? is_empty_directory(p, ec)
-      : path_stat.st_size == 0;
-#   else
+# else
 
-    WIN32_FILE_ATTRIBUTE_DATA fad;
-    if (error(::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad)== 0
-      ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::is_empty"))
-        return false;
+  WIN32_FILE_ATTRIBUTE_DATA fad;
+  if (error(::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad)== 0
+    ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::is_empty"))
+      return false;
 
-    if (ec != 0) ec->clear();
-    return 
-      (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-        ? is_empty_directory(p, ec)
-        : (!fad.nFileSizeHigh && !fad.nFileSizeLow);
-#   endif
-  }
+  if (ec != 0) ec->clear();
+  return
+    (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+      ? is_empty_directory(p, ec)
+      : (!fad.nFileSizeHigh && !fad.nFileSizeLow);
 
-  BOOST_FILESYSTEM_DECL
-  std::time_t last_write_time(const path& p, system::error_code* ec)
-  {
-#   ifdef BOOST_POSIX_API
+# endif
+}
 
-    struct stat path_stat;
-    if (error(::stat(p.c_str(), &path_stat)!= 0 ? BOOST_ERRNO : 0,
-      p, ec, "boost::filesystem::last_write_time"))
-        return std::time_t(-1);
-    return path_stat.st_mtime;
+BOOST_FILESYSTEM_DECL
+std::time_t last_write_time(const path& p, system::error_code* ec)
+{
+# ifdef BOOST_POSIX_API
 
-#   else
+  struct stat path_stat;
+  if (error(::stat(p.c_str(), &path_stat)!= 0 ? BOOST_ERRNO : 0,
+    p, ec, "boost::filesystem::last_write_time"))
+      return std::time_t(-1);
+  return path_stat.st_mtime;
 
-    handle_wrapper hw(
-      create_file_handle(p.c_str(), 0,
-        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
-        OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
+# else
 
-    if (error(hw.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0,
-      p, ec, "boost::filesystem::last_write_time"))
-        return std::time_t(-1);
+  handle_wrapper hw(
+    create_file_handle(p.c_str(), 0,
+      FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
+      OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
 
-    FILETIME lwt;
+  if (error(hw.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0,
+    p, ec, "boost::filesystem::last_write_time"))
+      return std::time_t(-1);
 
-    if (error(::GetFileTime(hw.handle, 0, 0, &lwt)== 0 ? BOOST_ERRNO : 0,
-      p, ec, "boost::filesystem::last_write_time"))
-        return std::time_t(-1);
+  FILETIME lwt;
 
-    return to_time_t(lwt);
-#   endif
-  }
+  if (error(::GetFileTime(hw.handle, 0, 0, &lwt)== 0 ? BOOST_ERRNO : 0,
+    p, ec, "boost::filesystem::last_write_time"))
+      return std::time_t(-1);
 
-  BOOST_FILESYSTEM_DECL
-  void last_write_time(const path& p, const std::time_t new_time,
-                        system::error_code* ec)
-  {
-#   ifdef BOOST_POSIX_API
+  return to_time_t(lwt);
 
-    struct stat path_stat;
-    if (error(::stat(p.c_str(), &path_stat)!= 0,
-      p, ec, "boost::filesystem::last_write_time"))
-        return;
-    ::utimbuf buf;
-    buf.actime = path_stat.st_atime; // utime()updates access time too:-(
-    buf.modtime = new_time;
-    error(::utime(p.c_str(), &buf)!= 0 ? BOOST_ERRNO : 0,
-      p, ec, "boost::filesystem::last_write_time");
+# endif
+}
 
-#   else
+BOOST_FILESYSTEM_DECL
+void last_write_time(const path& p, const std::time_t new_time,
+                      system::error_code* ec)
+{
+# ifdef BOOST_POSIX_API
+#   if _POSIX_C_SOURCE >= 200809L
 
-    handle_wrapper hw(
-      create_file_handle(p.c_str(), FILE_WRITE_ATTRIBUTES,
-        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
-        OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
+  struct timespec times[2] = {};
 
-    if (error(hw.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0,
-      p, ec, "boost::filesystem::last_write_time"))
-        return;
+  // Keep the last access time unchanged
+  times[0].tv_nsec = UTIME_OMIT;
 
-    FILETIME lwt;
-    to_FILETIME(new_time, lwt);
+  times[1].tv_sec = new_time;
 
-    error(::SetFileTime(hw.handle, 0, 0, &lwt)== 0 ? BOOST_ERRNO : 0,
-      p, ec, "boost::filesystem::last_write_time");
-#   endif
+  if (BOOST_UNLIKELY(::utimensat(AT_FDCWD, p.c_str(), times, 0) != 0))
+  {
+    error(BOOST_ERRNO, p, ec, "boost::filesystem::last_write_time");
+    return;
   }
 
-# ifdef BOOST_POSIX_API
-    const perms active_bits(all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit);
-    inline mode_t mode_cast(perms prms) { return prms & active_bits; }
-# endif
-
-  BOOST_FILESYSTEM_DECL
-  void permissions(const path& p, perms prms, system::error_code* ec)
-  {
-    BOOST_ASSERT_MSG(!((prms & add_perms) && (prms & remove_perms)),
-      "add_perms and remove_perms are mutually exclusive");
+#   else // _POSIX_C_SOURCE >= 200809L
 
-    if ((prms & add_perms) && (prms & remove_perms))  // precondition failed
+  struct stat path_stat;
+  if (error(::stat(p.c_str(), &path_stat)!= 0,
+    p, ec, "boost::filesystem::last_write_time"))
       return;
+  ::utimbuf buf;
+  buf.actime = path_stat.st_atime; // utime()updates access time too:-(
+  buf.modtime = new_time;
+  error(::utime(p.c_str(), &buf)!= 0 ? BOOST_ERRNO : 0,
+    p, ec, "boost::filesystem::last_write_time");
 
-# ifdef BOOST_POSIX_API
-    error_code local_ec;
-    file_status current_status((prms & symlink_perms)
-                               ? fs::symlink_status(p, local_ec)
-                               : fs::status(p, local_ec));
-    if (local_ec)
-    {
-      if (ec == 0)
-      BOOST_FILESYSTEM_THROW(filesystem_error(
-          "boost::filesystem::permissions", p, local_ec));
-      else
-        *ec = local_ec;
-      return;
-    }
+#   endif // _POSIX_C_SOURCE >= 200809L
 
-    if (prms & add_perms)
-      prms |= current_status.permissions();
-    else if (prms & remove_perms)
-      prms = current_status.permissions() & ~prms;
-
-    // OS X <10.10, iOS <8.0 and some other platforms don't support fchmodat().
-    // Solaris (SunPro and gcc) only support fchmodat() on Solaris 11 and higher,
-    // and a runtime check is too much trouble.
-    // Linux does not support permissions on symbolic links and has no plans to
-    // support them in the future.  The chmod() code is thus more practical,
-    // rather than always hitting ENOTSUP when sending in AT_SYMLINK_NO_FOLLOW.
-    //  - See the 3rd paragraph of
-    // "Symbolic link ownership, permissions, and timestamps" at:
-    //   "http://man7.org/linux/man-pages/man7/symlink.7.html"
-    //  - See the fchmodat() Linux man page:
-    //   "http://man7.org/linux/man-pages/man2/fchmodat.2.html"
-#   if defined(AT_FDCWD) && defined(AT_SYMLINK_NOFOLLOW) \
-      && !(defined(__SUNPRO_CC) || defined(__sun) || defined(sun)) \
-      && !(defined(linux) || defined(__linux) || defined(__linux__)) \
-      && !(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
-           && __MAC_OS_X_VERSION_MIN_REQUIRED < 101000) \
-      && !(defined(__IPHONE_OS_VERSION_MIN_REQUIRED) \
-           && __IPHONE_OS_VERSION_MIN_REQUIRED < 80000)
-      if (::fchmodat(AT_FDCWD, p.c_str(), mode_cast(prms),
-           !(prms & symlink_perms) ? 0 : AT_SYMLINK_NOFOLLOW))
-#   else  // fallback if fchmodat() not supported
-      if (::chmod(p.c_str(), mode_cast(prms)))
-#   endif
-    {
-      if (ec == 0)
-      BOOST_FILESYSTEM_THROW(filesystem_error(
-          "boost::filesystem::permissions", p,
-          error_code(errno, system::generic_category())));
-      else
-        ec->assign(errno, system::generic_category());
-    }
+# else
 
-# else  // Windows
+  handle_wrapper hw(
+    create_file_handle(p.c_str(), FILE_WRITE_ATTRIBUTES,
+      FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
+      OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
 
-    // if not going to alter FILE_ATTRIBUTE_READONLY, just return
-    if (!(!((prms & (add_perms | remove_perms)))
-      || (prms & (owner_write|group_write|others_write))))
+  if (error(hw.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0,
+    p, ec, "boost::filesystem::last_write_time"))
       return;
 
-    DWORD attr = ::GetFileAttributesW(p.c_str());
+  FILETIME lwt;
+  to_FILETIME(new_time, lwt);
 
-    if (error(attr == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::permissions"))
-      return;
+  error(::SetFileTime(hw.handle, 0, 0, &lwt)== 0 ? BOOST_ERRNO : 0,
+    p, ec, "boost::filesystem::last_write_time");
 
-    if (prms & add_perms)
-      attr &= ~FILE_ATTRIBUTE_READONLY;
-    else if (prms & remove_perms)
-      attr |= FILE_ATTRIBUTE_READONLY;
-    else if (prms & (owner_write|group_write|others_write))
-      attr &= ~FILE_ATTRIBUTE_READONLY;
-    else
-      attr |= FILE_ATTRIBUTE_READONLY;
+# endif
+}
 
-    error(::SetFileAttributesW(p.c_str(), attr) == 0 ? BOOST_ERRNO : 0,
-      p, ec, "boost::filesystem::permissions");
+# ifdef BOOST_POSIX_API
+const perms active_bits(all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit);
+inline mode_t mode_cast(perms prms) { return prms & active_bits; }
 # endif
-  }
 
-  BOOST_FILESYSTEM_DECL
-  path read_symlink(const path& p, system::error_code* ec)
-  {
-    path symlink_path;
+BOOST_FILESYSTEM_DECL
+void permissions(const path& p, perms prms, system::error_code* ec)
+{
+  BOOST_ASSERT_MSG(!((prms & add_perms) && (prms & remove_perms)),
+    "add_perms and remove_perms are mutually exclusive");
 
-#   ifdef BOOST_POSIX_API
+  if ((prms & add_perms) && (prms & remove_perms))  // precondition failed
+    return;
 
-    for (std::size_t path_max = 64;; path_max *= 2)// loop 'til buffer large enough
-    {
-      boost::scoped_array<char> buf(new char[path_max]);
-      ssize_t result;
-      if ((result=::readlink(p.c_str(), buf.get(), path_max))== -1)
-      {
-        if (ec == 0)
-          BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::read_symlink",
-            p, error_code(errno, system_category())));
-        else ec->assign(errno, system_category());
-        break;
-      }
-      else
-      {
-        if(result != static_cast<ssize_t>(path_max))
-        {
-          symlink_path.assign(buf.get(), buf.get() + result);
-          if (ec != 0) ec->clear();
-          break;
-        }
-      }
-    }
-
-#   elif _WIN32_WINNT < 0x0600  // SDK earlier than Vista and Server 2008
-    error(BOOST_ERROR_NOT_SUPPORTED, p, ec,
-          "boost::filesystem::read_symlink");
-#   else  // Vista and Server 2008 SDK, or later
-
-    union info_t
-    {
-      char buf[REPARSE_DATA_BUFFER_HEADER_SIZE+MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
-      REPARSE_DATA_BUFFER rdb;
-    } info;
-
-    handle_wrapper h(
-      create_file_handle(p.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING,
-        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0));
-
-    if (error(h.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0,
-      p, ec, "boost::filesystem::read_symlink"))
-        return symlink_path;
-
-    DWORD sz;
-
-    if (!error(::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT,
-          0, 0, info.buf, sizeof(info), &sz, 0) == 0 ? BOOST_ERRNO : 0, p, ec,
-          "boost::filesystem::read_symlink" ))
-      symlink_path.assign(
-        static_cast<wchar_t*>(info.rdb.SymbolicLinkReparseBuffer.PathBuffer)
-        + info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(wchar_t),
-        static_cast<wchar_t*>(info.rdb.SymbolicLinkReparseBuffer.PathBuffer)
-        + info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(wchar_t)
-        + info.rdb.SymbolicLinkReparseBuffer.PrintNameLength/sizeof(wchar_t));
-#     endif
-    return symlink_path;
-  }
-
-  BOOST_FILESYSTEM_DECL
-  path relative(const path& p, const path& base, error_code* ec)
+# ifdef BOOST_POSIX_API
+  error_code local_ec;
+  file_status current_status((prms & symlink_perms)
+                             ? fs::symlink_status(p, local_ec)
+                             : fs::status(p, local_ec));
+  if (local_ec)
   {
-    error_code tmp_ec;
-    path wc_base(weakly_canonical(base, &tmp_ec));
-    if (error(tmp_ec.value(), base, ec, "boost::filesystem::relative"))
-      return path();
-    path wc_p(weakly_canonical(p, &tmp_ec));
-    if (error(tmp_ec.value(), base, ec, "boost::filesystem::relative"))
-      return path();
-    return wc_p.lexically_relative(wc_base);
-  }
-  
-  BOOST_FILESYSTEM_DECL
-  bool remove(const path& p, error_code* ec)
+    if (ec == 0)
+    BOOST_FILESYSTEM_THROW(filesystem_error(
+        "boost::filesystem::permissions", p, local_ec));
+    else
+      *ec = local_ec;
+    return;
+  }
+
+  if (prms & add_perms)
+    prms |= current_status.permissions();
+  else if (prms & remove_perms)
+    prms = current_status.permissions() & ~prms;
+
+  // OS X <10.10, iOS <8.0 and some other platforms don't support fchmodat().
+  // Solaris (SunPro and gcc) only support fchmodat() on Solaris 11 and higher,
+  // and a runtime check is too much trouble.
+  // Linux does not support permissions on symbolic links and has no plans to
+  // support them in the future.  The chmod() code is thus more practical,
+  // rather than always hitting ENOTSUP when sending in AT_SYMLINK_NO_FOLLOW.
+  //  - See the 3rd paragraph of
+  // "Symbolic link ownership, permissions, and timestamps" at:
+  //   "http://man7.org/linux/man-pages/man7/symlink.7.html"
+  //  - See the fchmodat() Linux man page:
+  //   "http://man7.org/linux/man-pages/man2/fchmodat.2.html"
+# if defined(AT_FDCWD) && defined(AT_SYMLINK_NOFOLLOW) \
+    && !(defined(__SUNPRO_CC) || defined(__sun) || defined(sun)) \
+    && !(defined(linux) || defined(__linux) || defined(__linux__)) \
+    && !(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
+         && __MAC_OS_X_VERSION_MIN_REQUIRED < 101000) \
+    && !(defined(__IPHONE_OS_VERSION_MIN_REQUIRED) \
+         && __IPHONE_OS_VERSION_MIN_REQUIRED < 80000) \
+    && !(defined(__QNX__) && (_NTO_VERSION <= 700))
+  if (::fchmodat(AT_FDCWD, p.c_str(), mode_cast(prms),
+       !(prms & symlink_perms) ? 0 : AT_SYMLINK_NOFOLLOW))
+# else  // fallback if fchmodat() not supported
+  if (::chmod(p.c_str(), mode_cast(prms)))
+# endif
   {
-    error_code tmp_ec;
-    file_type type = query_file_type(p, &tmp_ec);
-    if (error(type == status_error ? tmp_ec.value() : 0, p, ec,
-        "boost::filesystem::remove"))
-      return false;
-
-    // Since POSIX remove() is specified to work with either files or directories, in a
-    // perfect world it could just be called. But some important real-world operating
-    // systems (Windows, Mac OS X, for example) don't implement the POSIX spec. So
-    // remove_file_or_directory() is always called to keep it simple.
-    return remove_file_or_directory(p, type, ec);
+    const int err = errno;
+    if (ec == 0)
+      BOOST_FILESYSTEM_THROW(filesystem_error(
+        "boost::filesystem::permissions", p,
+        error_code(err, system::generic_category())));
+    else
+      ec->assign(err, system::generic_category());
   }
 
-  BOOST_FILESYSTEM_DECL
-  boost::uintmax_t remove_all(const path& p, error_code* ec)
-  {
-    error_code tmp_ec;
-    file_type type = query_file_type(p, &tmp_ec);
-    if (error(type == status_error ? tmp_ec.value() : 0, p, ec,
-      "boost::filesystem::remove_all"))
-      return 0;
-
-    return (type != status_error && type != file_not_found) // exists
-      ? remove_all_aux(p, type, ec)
-      : 0;
-  }
+# else  // Windows
 
-  BOOST_FILESYSTEM_DECL
-  void rename(const path& old_p, const path& new_p, error_code* ec)
-  {
-    error(!BOOST_MOVE_FILE(old_p.c_str(), new_p.c_str()) ? BOOST_ERRNO : 0, old_p, new_p,
-      ec, "boost::filesystem::rename");
-  }
+  // if not going to alter FILE_ATTRIBUTE_READONLY, just return
+  if (!(!((prms & (add_perms | remove_perms)))
+    || (prms & (owner_write|group_write|others_write))))
+    return;
 
-  BOOST_FILESYSTEM_DECL
-  void resize_file(const path& p, uintmax_t size, system::error_code* ec)
-  {
-    error(!BOOST_RESIZE_FILE(p.c_str(), size) ? BOOST_ERRNO : 0, p, ec,
-      "boost::filesystem::resize_file");
-  }
+  DWORD attr = ::GetFileAttributesW(p.c_str());
 
-  BOOST_FILESYSTEM_DECL
-  space_info space(const path& p, error_code* ec)
-  {
-#   ifdef BOOST_POSIX_API
-    struct BOOST_STATVFS vfs;
-    space_info info;
-    if (!error(::BOOST_STATVFS(p.c_str(), &vfs) ? BOOST_ERRNO : 0,
-      p, ec, "boost::filesystem::space"))
-    {
-      info.capacity 
-        = static_cast<boost::uintmax_t>(vfs.f_blocks)* BOOST_STATVFS_F_FRSIZE;
-      info.free 
-        = static_cast<boost::uintmax_t>(vfs.f_bfree)* BOOST_STATVFS_F_FRSIZE;
-      info.available
-        = static_cast<boost::uintmax_t>(vfs.f_bavail)* BOOST_STATVFS_F_FRSIZE;
-    }
+  if (error(attr == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::permissions"))
+    return;
 
-#   else
-    ULARGE_INTEGER avail, total, free;
-    space_info info;
+  if (prms & add_perms)
+    attr &= ~FILE_ATTRIBUTE_READONLY;
+  else if (prms & remove_perms)
+    attr |= FILE_ATTRIBUTE_READONLY;
+  else if (prms & (owner_write|group_write|others_write))
+    attr &= ~FILE_ATTRIBUTE_READONLY;
+  else
+    attr |= FILE_ATTRIBUTE_READONLY;
 
-    if (!error(::GetDiskFreeSpaceExW(p.c_str(), &avail, &total, &free)== 0,
-       p, ec, "boost::filesystem::space"))
-    {
-      info.capacity
-        = (static_cast<boost::uintmax_t>(total.HighPart)<< 32)
-          + total.LowPart;
-      info.free
-        = (static_cast<boost::uintmax_t>(free.HighPart)<< 32)
-          + free.LowPart;
-      info.available
-        = (static_cast<boost::uintmax_t>(avail.HighPart)<< 32)
-          + avail.LowPart;
-    }
+  error(::SetFileAttributesW(p.c_str(), attr) == 0 ? BOOST_ERRNO : 0,
+    p, ec, "boost::filesystem::permissions");
+# endif
+}
 
-#   endif
+BOOST_FILESYSTEM_DECL
+path read_symlink(const path& p, system::error_code* ec)
+{
+  path symlink_path;
 
+# ifdef BOOST_POSIX_API
+  const char* const path_str = p.c_str();
+  char small_buf[1024];
+  ssize_t result = ::readlink(path_str, small_buf, sizeof(small_buf));
+  if (BOOST_UNLIKELY(result < 0))
+  {
+  fail:
+    const int err = errno;
+    if (ec == 0)
+      BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::read_symlink",
+        p, error_code(err, system_category())));
     else
-    {
-      info.capacity = info.free = info.available = 0;
-    }
-    return info;
+      ec->assign(err, system_category());
   }
-
-  BOOST_FILESYSTEM_DECL
-  file_status status(const path& p, error_code* ec)
+  else if (BOOST_LIKELY(static_cast< std::size_t >(result) < sizeof(small_buf)))
   {
-#   ifdef BOOST_POSIX_API
-
-    struct stat path_stat;
-    if (::stat(p.c_str(), &path_stat)!= 0)
+    symlink_path.assign(small_buf, small_buf + result);
+    if (ec != 0)
+      ec->clear();
+  }
+  else
+  {
+    for (std::size_t path_max = sizeof(small_buf) * 2u;; path_max *= 2u) // loop 'til buffer large enough
     {
-      if (ec != 0)                            // always report errno, even though some
-        ec->assign(errno, system_category());   // errno values are not status_errors
-
-      if (not_found_error(errno))
+      if (BOOST_UNLIKELY(path_max > absolute_path_max))
       {
-        return fs::file_status(fs::file_not_found, fs::no_perms);
+        if (ec == 0)
+          BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::read_symlink",
+            p, error_code(ENAMETOOLONG, system_category())));
+        else
+          ec->assign(ENAMETOOLONG, system_category());
+        break;
       }
-      if (ec == 0)
-        BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
-          p, error_code(errno, system_category())));
-      return fs::file_status(fs::status_error);
-    }
-    if (ec != 0) ec->clear();;
-    if (S_ISDIR(path_stat.st_mode))
-      return fs::file_status(fs::directory_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    if (S_ISREG(path_stat.st_mode))
-      return fs::file_status(fs::regular_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    if (S_ISBLK(path_stat.st_mode))
-      return fs::file_status(fs::block_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    if (S_ISCHR(path_stat.st_mode))
-      return fs::file_status(fs::character_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    if (S_ISFIFO(path_stat.st_mode))
-      return fs::file_status(fs::fifo_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    if (S_ISSOCK(path_stat.st_mode))
-      return fs::file_status(fs::socket_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    return fs::file_status(fs::type_unknown);
-
-#   else  // Windows
-
-    DWORD attr(::GetFileAttributesW(p.c_str()));
-    if (attr == 0xFFFFFFFF)
-    {
-      return process_status_failure(p, ec);
-    }
 
-    //  reparse point handling;
-    //    since GetFileAttributesW does not resolve symlinks, try to open a file
-    //    handle to discover if the file exists
-    if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
-    {
-      handle_wrapper h(
-        create_file_handle(
-            p.c_str(),
-            0,  // dwDesiredAccess; attributes only
-            FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
-            0,  // lpSecurityAttributes
-            OPEN_EXISTING,
-            FILE_FLAG_BACKUP_SEMANTICS,
-            0)); // hTemplateFile
-      if (h.handle == INVALID_HANDLE_VALUE)
+      boost::scoped_array<char> buf(new char[path_max]);
+      result = ::readlink(path_str, buf.get(), path_max);
+      if (BOOST_UNLIKELY(result < 0))
       {
-        return process_status_failure(p, ec);
+        goto fail;
+      }
+      else if (BOOST_LIKELY(static_cast< std::size_t >(result) < path_max))
+      {
+        symlink_path.assign(buf.get(), buf.get() + result);
+        if (ec != 0) ec->clear();
+        break;
       }
-
-      if (!is_reparse_point_a_symlink(p))
-        return file_status(reparse_file, make_permissions(p, attr));
     }
-
-    if (ec != 0) ec->clear();
-    return (attr & FILE_ATTRIBUTE_DIRECTORY)
-      ? file_status(directory_file, make_permissions(p, attr))
-      : file_status(regular_file, make_permissions(p, attr));
-
-#   endif
   }
 
-  BOOST_FILESYSTEM_DECL
-  file_status symlink_status(const path& p, error_code* ec)
+# elif _WIN32_WINNT < 0x0600  // SDK earlier than Vista and Server 2008
+  error(BOOST_ERROR_NOT_SUPPORTED, p, ec,
+        "boost::filesystem::read_symlink");
+# else  // Vista and Server 2008 SDK, or later
+
+  union info_t
   {
-#   ifdef BOOST_POSIX_API
+    char buf[REPARSE_DATA_BUFFER_HEADER_SIZE+MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+    REPARSE_DATA_BUFFER rdb;
+  } info;
 
-    struct stat path_stat;
-    if (::lstat(p.c_str(), &path_stat)!= 0)
-    {
-      if (ec != 0)                            // always report errno, even though some
-        ec->assign(errno, system_category());   // errno values are not status_errors
+  handle_wrapper h(
+    create_file_handle(p.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING,
+      FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0));
 
-      if (errno == ENOENT || errno == ENOTDIR) // these are not errors
-      {
-        return fs::file_status(fs::file_not_found, fs::no_perms);
-      }
-      if (ec == 0)
-        BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
-          p, error_code(errno, system_category())));
-      return fs::file_status(fs::status_error);
-    }
-    if (ec != 0) ec->clear();
-    if (S_ISREG(path_stat.st_mode))
-      return fs::file_status(fs::regular_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    if (S_ISDIR(path_stat.st_mode))
-      return fs::file_status(fs::directory_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    if (S_ISLNK(path_stat.st_mode))
-      return fs::file_status(fs::symlink_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    if (S_ISBLK(path_stat.st_mode))
-      return fs::file_status(fs::block_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    if (S_ISCHR(path_stat.st_mode))
-      return fs::file_status(fs::character_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    if (S_ISFIFO(path_stat.st_mode))
-      return fs::file_status(fs::fifo_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    if (S_ISSOCK(path_stat.st_mode))
-      return fs::file_status(fs::socket_file,
-        static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
-    return fs::file_status(fs::type_unknown);
+  if (error(h.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0,
+    p, ec, "boost::filesystem::read_symlink"))
+      return symlink_path;
 
-#   else  // Windows
+  DWORD sz;
 
-    DWORD attr(::GetFileAttributesW(p.c_str()));
-    if (attr == 0xFFFFFFFF)
-    {
-      return process_status_failure(p, ec);
-    }
-
-    if (ec != 0) ec->clear();
+  if (!error(::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT,
+        0, 0, info.buf, sizeof(info), &sz, 0) == 0 ? BOOST_ERRNO : 0, p, ec,
+        "boost::filesystem::read_symlink" ))
+    symlink_path.assign(
+      static_cast<wchar_t*>(info.rdb.SymbolicLinkReparseBuffer.PathBuffer)
+      + info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(wchar_t),
+      static_cast<wchar_t*>(info.rdb.SymbolicLinkReparseBuffer.PathBuffer)
+      + info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(wchar_t)
+      + info.rdb.SymbolicLinkReparseBuffer.PrintNameLength/sizeof(wchar_t));
+# endif
+  return symlink_path;
+}
 
-    if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
-      return is_reparse_point_a_symlink(p)
-             ? file_status(symlink_file, make_permissions(p, attr))
-             : file_status(reparse_file, make_permissions(p, attr));
+BOOST_FILESYSTEM_DECL
+path relative(const path& p, const path& base, error_code* ec)
+{
+  error_code tmp_ec;
+  path wc_base(weakly_canonical(base, &tmp_ec));
+  if (error(tmp_ec.value(), base, ec, "boost::filesystem::relative"))
+    return path();
+  path wc_p(weakly_canonical(p, &tmp_ec));
+  if (error(tmp_ec.value(), base, ec, "boost::filesystem::relative"))
+    return path();
+  return wc_p.lexically_relative(wc_base);
+}
 
-    return (attr & FILE_ATTRIBUTE_DIRECTORY)
-      ? file_status(directory_file, make_permissions(p, attr))
-      : file_status(regular_file, make_permissions(p, attr));
+BOOST_FILESYSTEM_DECL
+bool remove(const path& p, error_code* ec)
+{
+  error_code tmp_ec;
+  file_type type = query_file_type(p, &tmp_ec);
+  if (error(type == status_error ? tmp_ec.value() : 0, p, ec,
+      "boost::filesystem::remove"))
+    return false;
 
-#   endif
-  }
+  // Since POSIX remove() is specified to work with either files or directories, in a
+  // perfect world it could just be called. But some important real-world operating
+  // systems (Windows, Mac OS X, for example) don't implement the POSIX spec. So
+  // remove_file_or_directory() is always called to keep it simple.
+  return remove_file_or_directory(p, type, ec);
+}
 
-   // contributed by Jeff Flinn
-  BOOST_FILESYSTEM_DECL
-  path temp_directory_path(system::error_code* ec)
-  {
-#   ifdef BOOST_POSIX_API
-      const char* val = 0;
-      
-      (val = std::getenv("TMPDIR" )) ||
-      (val = std::getenv("TMP"    )) ||
-      (val = std::getenv("TEMP"   )) ||
-      (val = std::getenv("TEMPDIR"));
-      
-#     ifdef __ANDROID__
-        const char* default_tmp = "/data/local/tmp";
-#     else
-        const char* default_tmp = "/tmp";
-#     endif
-      path p((val!=0) ? val : default_tmp);
-       
-      if (p.empty() || (ec&&!is_directory(p, *ec))||(!ec&&!is_directory(p)))
-      {
-        error(ENOTDIR, p, ec, "boost::filesystem::temp_directory_path");
-        return p;
-      }
-        
-      return p;
-      
-#   else  // Windows
-
-      const wchar_t* tmp_env = L"TMP";
-      const wchar_t* temp_env = L"TEMP";
-      const wchar_t* localappdata_env = L"LOCALAPPDATA";
-      const wchar_t* userprofile_env = L"USERPROFILE";
-      const wchar_t* env_list[]
-        = {tmp_env, temp_env, localappdata_env, userprofile_env, 0};
-
-      path p;
-      for (int i = 0; env_list[i]; ++i)
-      {
-        std::wstring env = wgetenv(env_list[i]);
-        if (!env.empty())
-        {
-          p = env;
-          if (i >= 2)
-            p /= L"Temp";
-          error_code lcl_ec;
-          if (exists(p, lcl_ec) && !lcl_ec && is_directory(p, lcl_ec) && !lcl_ec)
-            break;
-          p.clear();
-        }
-      }
+BOOST_FILESYSTEM_DECL
+boost::uintmax_t remove_all(const path& p, error_code* ec)
+{
+  error_code tmp_ec;
+  file_type type = query_file_type(p, &tmp_ec);
+  if (error(type == status_error ? tmp_ec.value() : 0, p, ec,
+    "boost::filesystem::remove_all"))
+    return 0;
 
-      if (p.empty())
-      {
-        // use vector since in C++03 a string is not required to be contiguous
-        std::vector<wchar_t> buf(::GetWindowsDirectoryW(NULL, 0));
+  return (type != status_error && type != file_not_found) // exists
+    ? remove_all_aux(p, type, ec)
+    : 0;
+}
 
-        if (buf.empty()
-          || ::GetWindowsDirectoryW(&buf[0], static_cast<UINT>(buf.size())) == 0)
-        {
-          error(::GetLastError(), ec, "boost::filesystem::temp_directory_path");
-          return path();
-        }
-        p = &*buf.begin();  // do not depend on buf.size(); see ticket #10388
-        p /= L"Temp";
-      }
-      return p;
+BOOST_FILESYSTEM_DECL
+void rename(const path& old_p, const path& new_p, error_code* ec)
+{
+  error(!BOOST_MOVE_FILE(old_p.c_str(), new_p.c_str()) ? BOOST_ERRNO : 0, old_p, new_p,
+    ec, "boost::filesystem::rename");
+}
 
-#   endif
+BOOST_FILESYSTEM_DECL
+void resize_file(const path& p, uintmax_t size, system::error_code* ec)
+{
+# if defined(BOOST_POSIX_API)
+  if (BOOST_UNLIKELY(size > static_cast< uintmax_t >((std::numeric_limits< off_t >::max)()))) {
+    error(system::errc::file_too_large, p, ec, "boost::filesystem::resize_file");
+    return;
   }
-  
-  BOOST_FILESYSTEM_DECL
-  path system_complete(const path& p, system::error_code* ec)
+# endif
+  error(!BOOST_RESIZE_FILE(p.c_str(), size) ? BOOST_ERRNO : 0, p, ec,
+    "boost::filesystem::resize_file");
+}
+
+BOOST_FILESYSTEM_DECL
+space_info space(const path& p, error_code* ec)
+{
+# ifdef BOOST_POSIX_API
+  struct BOOST_STATVFS vfs;
+  space_info info;
+  if (!error(::BOOST_STATVFS(p.c_str(), &vfs) ? BOOST_ERRNO : 0,
+    p, ec, "boost::filesystem::space"))
   {
-#   ifdef BOOST_POSIX_API
-    return (p.empty() || p.is_absolute())
-      ? p : current_path()/ p;
+    info.capacity
+      = static_cast<boost::uintmax_t>(vfs.f_blocks)* BOOST_STATVFS_F_FRSIZE;
+    info.free
+      = static_cast<boost::uintmax_t>(vfs.f_bfree)* BOOST_STATVFS_F_FRSIZE;
+    info.available
+      = static_cast<boost::uintmax_t>(vfs.f_bavail)* BOOST_STATVFS_F_FRSIZE;
+  }
 
-#   else
-    if (p.empty())
-    {
-      if (ec != 0) ec->clear();
-      return p;
-    }
-    wchar_t buf[buf_size];
-    wchar_t* pfn;
-    std::size_t len = get_full_path_name(p, buf_size, buf, &pfn);
+# else
 
-    if (error(len == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::system_complete"))
-      return path();
+  ULARGE_INTEGER avail, total, free;
+  space_info info;
 
-    if (len < buf_size)// len does not include null termination character
-      return path(&buf[0]);
+  if (!error(::GetDiskFreeSpaceExW(p.c_str(), &avail, &total, &free)== 0,
+     p, ec, "boost::filesystem::space"))
+  {
+    info.capacity
+      = (static_cast<boost::uintmax_t>(total.HighPart)<< 32)
+        + total.LowPart;
+    info.free
+      = (static_cast<boost::uintmax_t>(free.HighPart)<< 32)
+        + free.LowPart;
+    info.available
+      = (static_cast<boost::uintmax_t>(avail.HighPart)<< 32)
+        + avail.LowPart;
+  }
 
-    boost::scoped_array<wchar_t> big_buf(new wchar_t[len]);
+# endif
 
-    return error(get_full_path_name(p, len , big_buf.get(), &pfn)== 0 ? BOOST_ERRNO : 0,
-      p, ec, "boost::filesystem::system_complete")
-      ? path()
-      : path(big_buf.get());
-#   endif
+  else
+  {
+    info.capacity = info.free = info.available = 0;
   }
+  return info;
+}
+
+BOOST_FILESYSTEM_DECL
+file_status status(const path& p, error_code* ec)
+{
+# ifdef BOOST_POSIX_API
 
-  BOOST_FILESYSTEM_DECL
-  path weakly_canonical(const path& p, system::error_code* ec)
+  struct stat path_stat;
+  if (::stat(p.c_str(), &path_stat)!= 0)
   {
-    path head(p);
-    path tail;
-    system::error_code tmp_ec;
-    path::iterator itr = p.end();
+    const int err = errno;
+    if (ec != 0)                            // always report errno, even though some
+      ec->assign(err, system_category());   // errno values are not status_errors
 
-    for (; !head.empty(); --itr)
+    if (not_found_error(err))
     {
-      file_status head_status = status(head, tmp_ec);
-      if (error(head_status.type() == fs::status_error,
-        head, ec, "boost::filesystem::weakly_canonical"))
-        return path();
-      if (head_status.type() != fs::file_not_found)
-        break;
-      head.remove_filename();
+      return fs::file_status(fs::file_not_found, fs::no_perms);
     }
+    if (ec == 0)
+      BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
+        p, error_code(err, system_category())));
+    return fs::file_status(fs::status_error);
+  }
+  if (ec != 0) ec->clear();;
+  if (S_ISDIR(path_stat.st_mode))
+    return fs::file_status(fs::directory_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  if (S_ISREG(path_stat.st_mode))
+    return fs::file_status(fs::regular_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  if (S_ISBLK(path_stat.st_mode))
+    return fs::file_status(fs::block_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  if (S_ISCHR(path_stat.st_mode))
+    return fs::file_status(fs::character_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  if (S_ISFIFO(path_stat.st_mode))
+    return fs::file_status(fs::fifo_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  if (S_ISSOCK(path_stat.st_mode))
+    return fs::file_status(fs::socket_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  return fs::file_status(fs::type_unknown);
 
-    bool tail_has_dots = false;
-    for (; itr != p.end(); ++itr)
-    { 
-      tail /= *itr;
-      // for a later optimization, track if any dot or dot-dot elements are present
-      if (itr->native().size() <= 2
-        && itr->native()[0] == dot
-        && (itr->native().size() == 1 || itr->native()[1] == dot))
-        tail_has_dots = true;
-    }
-    
-    if (head.empty())
-      return p.lexically_normal();
-    head = canonical(head, tmp_ec);
-    if (error(tmp_ec.value(), head, ec, "boost::filesystem::weakly_canonical"))
-      return path();
-    return tail.empty()
-      ? head
-      : (tail_has_dots  // optimization: only normalize if tail had dot or dot-dot element
-          ? (head/tail).lexically_normal()  
-          : head/tail);
+# else  // Windows
+
+  DWORD attr(::GetFileAttributesW(p.c_str()));
+  if (attr == 0xFFFFFFFF)
+  {
+    return process_status_failure(p, ec);
   }
-}  // namespace detail
 
-//--------------------------------------------------------------------------------------//
-//                                                                                      //
-//                                 directory_entry                                      //
-//                                                                                      //
-//--------------------------------------------------------------------------------------//
+  perms permissions = make_permissions(p, attr);
 
-  file_status
-  directory_entry::m_get_status(system::error_code* ec) const
+  //  reparse point handling;
+  //    since GetFileAttributesW does not resolve symlinks, try to open a file
+  //    handle to discover if the file exists
+  if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
   {
-    if (!status_known(m_status))
+    handle_wrapper h(
+      create_file_handle(
+          p.c_str(),
+          0,  // dwDesiredAccess; attributes only
+          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+          0,  // lpSecurityAttributes
+          OPEN_EXISTING,
+          FILE_FLAG_BACKUP_SEMANTICS,
+          0)); // hTemplateFile
+    if (h.handle == INVALID_HANDLE_VALUE)
     {
-      // optimization: if the symlink status is known, and it isn't a symlink,
-      // then status and symlink_status are identical so just copy the
-      // symlink status to the regular status.
-      if (status_known(m_symlink_status)
-        && !is_symlink(m_symlink_status))
-      { 
-        m_status = m_symlink_status;
-        if (ec != 0) ec->clear();
-      }
-      else m_status = detail::status(m_path, ec);
+      return process_status_failure(p, ec);
     }
-    else if (ec != 0) ec->clear();
-    return m_status;
-  }
 
-  file_status
-  directory_entry::m_get_symlink_status(system::error_code* ec) const
-  {
-    if (!status_known(m_symlink_status))
-      m_symlink_status = detail::symlink_status(m_path, ec);
-    else if (ec != 0) ec->clear();
-    return m_symlink_status;
+    if (!is_reparse_point_a_symlink(p))
+      return file_status(reparse_file, permissions);
   }
 
-//  dispatch directory_entry supplied here rather than in 
-//  <boost/filesystem/path_traits.hpp>, thus avoiding header circularity.
-//  test cases are in operations_unit_test.cpp
+  if (ec != 0) ec->clear();
+  return (attr & FILE_ATTRIBUTE_DIRECTORY)
+    ? file_status(directory_file, permissions)
+    : file_status(regular_file, permissions);
+
+# endif
+}
 
-namespace path_traits
+BOOST_FILESYSTEM_DECL
+file_status symlink_status(const path& p, error_code* ec)
 {
-  void dispatch(const directory_entry & de,
-#                ifdef BOOST_WINDOWS_API
-    std::wstring& to,
-#                else   
-    std::string& to,
-#                endif
-    const codecvt_type &)
+# ifdef BOOST_POSIX_API
+
+  struct stat path_stat;
+  if (::lstat(p.c_str(), &path_stat)!= 0)
   {
-    to = de.path().native();
+    const int err = errno;
+    if (ec != 0)                            // always report errno, even though some
+      ec->assign(err, system_category());   // errno values are not status_errors
+
+    if (not_found_error(err)) // these are not errors
+    {
+      return fs::file_status(fs::file_not_found, fs::no_perms);
+    }
+    if (ec == 0)
+      BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
+        p, error_code(err, system_category())));
+    return fs::file_status(fs::status_error);
   }
+  if (ec != 0) ec->clear();
+  if (S_ISREG(path_stat.st_mode))
+    return fs::file_status(fs::regular_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  if (S_ISDIR(path_stat.st_mode))
+    return fs::file_status(fs::directory_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  if (S_ISLNK(path_stat.st_mode))
+    return fs::file_status(fs::symlink_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  if (S_ISBLK(path_stat.st_mode))
+    return fs::file_status(fs::block_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  if (S_ISCHR(path_stat.st_mode))
+    return fs::file_status(fs::character_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  if (S_ISFIFO(path_stat.st_mode))
+    return fs::file_status(fs::fifo_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  if (S_ISSOCK(path_stat.st_mode))
+    return fs::file_status(fs::socket_file,
+      static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
+  return fs::file_status(fs::type_unknown);
 
-  void dispatch(const directory_entry & de,
-#                ifdef BOOST_WINDOWS_API
-    std::wstring& to
-#                else   
-    std::string& to
-#                endif
-    )
+# else  // Windows
+
+  DWORD attr(::GetFileAttributesW(p.c_str()));
+  if (attr == 0xFFFFFFFF)
   {
-    to = de.path().native();
+    return process_status_failure(p, ec);
   }
-}  // namespace path_traits
-} // namespace filesystem
-} // namespace boost
 
-//--------------------------------------------------------------------------------------//
-//                                                                                      //
-//                               directory_iterator                                     //
-//                                                                                      //
-//--------------------------------------------------------------------------------------//
+  if (ec != 0) ec->clear();
+
+  perms permissions = make_permissions(p, attr);
+
+  if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
+    return is_reparse_point_a_symlink(p)
+           ? file_status(symlink_file, permissions)
+           : file_status(reparse_file, permissions);
 
-namespace
+  return (attr & FILE_ATTRIBUTE_DIRECTORY)
+    ? file_status(directory_file, permissions)
+    : file_status(regular_file, permissions);
+
+# endif
+}
+
+ // contributed by Jeff Flinn
+BOOST_FILESYSTEM_DECL
+path temp_directory_path(system::error_code* ec)
 {
 # ifdef BOOST_POSIX_API
+  const char* val = 0;
 
-  error_code path_max(std::size_t & result)
-  // this code is based on Stevens and Rago, Advanced Programming in the
-  // UNIX envirnment, 2nd Ed., ISBN 0-201-43307-9, page 49
-  {
-#   ifdef PATH_MAX
-    static std::size_t max = PATH_MAX;
+  (val = std::getenv("TMPDIR" )) ||
+  (val = std::getenv("TMP"    )) ||
+  (val = std::getenv("TEMP"   )) ||
+  (val = std::getenv("TEMPDIR"));
+
+#   ifdef __ANDROID__
+  const char* default_tmp = "/data/local/tmp";
 #   else
-    static std::size_t max = 0;
+  const char* default_tmp = "/tmp";
 #   endif
-    if (max == 0)
-    {
-      errno = 0;
-      long tmp = ::pathconf("/", _PC_NAME_MAX);
-      if (tmp < 0)
-      {
-        if (errno == 0)// indeterminate
-          max = 4096; // guess
-        else return error_code(errno, system_category());
-      }
-      else max = static_cast<std::size_t>(tmp + 1); // relative root
-    }
-    result = max;
-    return ok;
-  }
+  path p((val != NULL) ? val : default_tmp);
 
-#if defined(__PGI) && defined(__USE_FILE_OFFSET64)
-#define dirent dirent64
-#endif
-
-  error_code dir_itr_first(void *& handle, void *& buffer,
-    const char* dir, string& target,
-    fs::file_status &, fs::file_status &)
+  if (p.empty() || (ec && !is_directory(p, *ec)) || (!ec && !is_directory(p)))
   {
-    if ((handle = ::opendir(dir))== 0)
-      return error_code(errno, system_category());
-    target = string(".");  // string was static but caused trouble
-                             // when iteration called from dtor, after
-                             // static had already been destroyed
-    std::size_t path_size (0);  // initialization quiets gcc warning (ticket #3509)
-    error_code ec = path_max(path_size);
-    if (ec)return ec;
-    dirent de;
-    buffer = std::malloc((sizeof(dirent) - sizeof(de.d_name))
-      +  path_size + 1); // + 1 for "/0"
-    return ok;
-  }  
-
-  // warning: the only dirent member updated is d_name
-  inline int readdir_r_simulator(DIR * dirp, struct dirent * entry,
-    struct dirent ** result)// *result set to 0 on end of directory
-  {
-    errno = 0;
-
-#   if !defined(__CYGWIN__)\
-    && defined(_POSIX_THREAD_SAFE_FUNCTIONS)\
-    && defined(_SC_THREAD_SAFE_FUNCTIONS)\
-    && (_POSIX_THREAD_SAFE_FUNCTIONS+0 >= 0)\
-    && (!defined(__hpux) || defined(_REENTRANT)) \
-    && (!defined(_AIX) || defined(__THREAD_SAFE))
-    if (::sysconf(_SC_THREAD_SAFE_FUNCTIONS)>= 0)
-      { return ::readdir_r(dirp, entry, result); }
-#   endif
-
-    struct dirent * p;
-    *result = 0;
-    if ((p = ::readdir(dirp))== 0)
-      return errno;
-    std::strcpy(entry->d_name, p->d_name);
-    *result = entry;
-    return 0;
+    error(ENOTDIR, p, ec, "boost::filesystem::temp_directory_path");
+    return p;
   }
 
-  error_code dir_itr_increment(void *& handle, void *& buffer,
-    string& target, fs::file_status & sf, fs::file_status & symlink_sf)
-  {
-    BOOST_ASSERT(buffer != 0);
-    dirent * entry(static_cast<dirent *>(buffer));
-    dirent * result;
-    int return_code;
-    if ((return_code = readdir_r_simulator(static_cast<DIR*>(handle), entry, &result))!= 0)
-      return error_code(errno, system_category());
-    if (result == 0)
-      return fs::detail::dir_itr_close(handle, buffer);
-    target = entry->d_name;
-#   ifdef BOOST_FILESYSTEM_STATUS_CACHE
-    if (entry->d_type == DT_UNKNOWN) // filesystem does not supply d_type value
-    {
-      sf = symlink_sf = fs::file_status(fs::status_error);
-    }
-    else  // filesystem supplies d_type value
-    {
-      if (entry->d_type == DT_DIR)
-        sf = symlink_sf = fs::file_status(fs::directory_file);
-      else if (entry->d_type == DT_REG)
-        sf = symlink_sf = fs::file_status(fs::regular_file);
-      else if (entry->d_type == DT_LNK)
-      {
-        sf = fs::file_status(fs::status_error);
-        symlink_sf = fs::file_status(fs::symlink_file);
-      }
-      else sf = symlink_sf = fs::file_status(fs::status_error);
-    }
-#   else
-    sf = symlink_sf = fs::file_status(fs::status_error);
-#    endif
-    return ok;
-  }
+  return p;
 
-# else // BOOST_WINDOWS_API
+# else  // Windows
+
+  const wchar_t* tmp_env = L"TMP";
+  const wchar_t* temp_env = L"TEMP";
+  const wchar_t* localappdata_env = L"LOCALAPPDATA";
+  const wchar_t* userprofile_env = L"USERPROFILE";
+  const wchar_t* env_list[] = { tmp_env, temp_env, localappdata_env, userprofile_env };
 
-  error_code dir_itr_first(void *& handle, const fs::path& dir,
-    wstring& target, fs::file_status & sf, fs::file_status & symlink_sf)
-  // Note: an empty root directory has no "." or ".." entries, so this
-  // causes a ERROR_FILE_NOT_FOUND error which we do not considered an
-  // error. It is treated as eof instead.
+  path p;
+  for (unsigned int i = 0; i < sizeof(env_list) / sizeof(*env_list); ++i)
   {
-    // use a form of search Sebastian Martel reports will work with Win98
-    wstring dirpath(dir.wstring());
-    dirpath += (dirpath.empty()
-      || (dirpath[dirpath.size()-1] != L'\\'
-        && dirpath[dirpath.size()-1] != L'/'
-        && dirpath[dirpath.size()-1] != L':'))? L"\\*" : L"*";
-
-    WIN32_FIND_DATAW data;
-    if ((handle = ::FindFirstFileW(dirpath.c_str(), &data))
-      == INVALID_HANDLE_VALUE)
-    { 
-      handle = 0;  // signal eof
-      return error_code( (::GetLastError() == ERROR_FILE_NOT_FOUND
-                       // Windows Mobile returns ERROR_NO_MORE_FILES; see ticket #3551                                           
-                       || ::GetLastError() == ERROR_NO_MORE_FILES) 
-        ? 0 : ::GetLastError(), system_category() );
-    }
-    target = data.cFileName;
-    if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
-    // reparse points are complex, so don't try to handle them here; instead just mark
-    // them as status_error which causes directory_entry caching to call status()
-    // and symlink_status() which do handle reparse points fully
+    std::wstring env = wgetenv(env_list[i]);
+    if (!env.empty())
     {
-      sf.type(fs::status_error);
-      symlink_sf.type(fs::status_error);
-    }
-    else
-    {
-      if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-      {
-        sf.type(fs::directory_file);
-        symlink_sf.type(fs::directory_file);
-      }
-      else
-      {
-        sf.type(fs::regular_file);
-        symlink_sf.type(fs::regular_file);
-      }
-      sf.permissions(make_permissions(data.cFileName, data.dwFileAttributes));
-      symlink_sf.permissions(sf.permissions());
+      p = env;
+      if (i >= 2)
+        p /= L"Temp";
+      error_code lcl_ec;
+      if (exists(p, lcl_ec) && !lcl_ec && is_directory(p, lcl_ec) && !lcl_ec)
+        break;
+      p.clear();
     }
-    return error_code();
   }
 
-  error_code  dir_itr_increment(void *& handle, wstring& target,
-    fs::file_status & sf, fs::file_status & symlink_sf)
+  if (p.empty())
   {
-    WIN32_FIND_DATAW data;
-    if (::FindNextFileW(handle, &data)== 0)// fails
+    // use a separate buffer since in C++03 a string is not required to be contiguous
+    const UINT size = ::GetWindowsDirectoryW(NULL, 0);
+    if (BOOST_UNLIKELY(size == 0))
     {
-      int error = ::GetLastError();
-      fs::detail::dir_itr_close(handle);
-      return error_code(error == ERROR_NO_MORE_FILES ? 0 : error, system_category());
-    }
-    target = data.cFileName;
-    if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
-    // reparse points are complex, so don't try to handle them here; instead just mark
-    // them as status_error which causes directory_entry caching to call status()
-    // and symlink_status() which do handle reparse points fully
-    {
-      sf.type(fs::status_error);
-      symlink_sf.type(fs::status_error);
-    }
-    else
-    {
-      if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-      {
-        sf.type(fs::directory_file);
-        symlink_sf.type(fs::directory_file);
-      }
-      else
-      {
-        sf.type(fs::regular_file);
-        symlink_sf.type(fs::regular_file);
-      }
-      sf.permissions(make_permissions(data.cFileName, data.dwFileAttributes));
-      symlink_sf.permissions(sf.permissions());
+    getwindir_error:
+      int errval = ::GetLastError();
+      error(errval, ec, "boost::filesystem::temp_directory_path");
+      return path();
     }
-    return error_code();
+
+    boost::scoped_array<wchar_t> buf(new wchar_t[size]);
+    if (BOOST_UNLIKELY(::GetWindowsDirectoryW(buf.get(), size) == 0))
+      goto getwindir_error;
+
+    p = buf.get();  // do not depend on initial buf size, see ticket #10388
+    p /= L"Temp";
   }
-#endif
 
-  const error_code not_found_error_code (
-#     ifdef BOOST_WINDOWS_API
-        ERROR_PATH_NOT_FOUND
-#     else
-        ENOENT 
-#     endif
-        , system_category());
+  return p;
 
-}  // unnamed namespace
+# endif
+}
 
-namespace boost
-{
-namespace filesystem
+BOOST_FILESYSTEM_DECL
+path system_complete(const path& p, system::error_code* ec)
 {
+# ifdef BOOST_POSIX_API
+  return (p.empty() || p.is_absolute())
+    ? p : current_path() / p;
 
-namespace detail
-{
-  //  dir_itr_close is called both from the ~dir_itr_imp()destructor 
-  //  and dir_itr_increment()
-  BOOST_FILESYSTEM_DECL
-  system::error_code dir_itr_close( // never throws
-    void *& handle
-#   if defined(BOOST_POSIX_API)
-    , void *& buffer
-#   endif
-   )
+# else
+  if (p.empty())
   {
-#   ifdef BOOST_POSIX_API
-    std::free(buffer);
-    buffer = 0;
-    if (handle == 0)return ok;
-    DIR * h(static_cast<DIR*>(handle));
-    handle = 0;
-    return error_code(::closedir(h)== 0 ? 0 : errno, system_category());
-
-#   else
-    if (handle != 0)
-    {
-      ::FindClose(handle);
-      handle = 0;
-    }
-    return ok;
-
-#   endif
+    if (ec != 0) ec->clear();
+    return p;
   }
+  wchar_t buf[buf_size];
+  wchar_t* pfn;
+  std::size_t len = get_full_path_name(p, buf_size, buf, &pfn);
 
-  void directory_iterator_construct(directory_iterator& it,
-    const path& p, system::error_code* ec)    
-  {
-    if (error(p.empty() ? not_found_error_code.value() : 0, p, ec,
-              "boost::filesystem::directory_iterator::construct"))
-      return;
+  if (error(len == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::system_complete"))
+    return path();
 
-    path::string_type filename;
-    file_status file_stat, symlink_file_stat;
-    error_code result = dir_itr_first(it.m_imp->handle,
-#     if defined(BOOST_POSIX_API)
-      it.m_imp->buffer,
-#     endif
-      p.c_str(), filename, file_stat, symlink_file_stat);
+  if (len < buf_size)// len does not include null termination character
+    return path(&buf[0]);
 
-    if (result)
-    {
-      it.m_imp.reset();
-      error(result.value(), p,
-        ec, "boost::filesystem::directory_iterator::construct");
-      return;
-    }
-    
-    if (it.m_imp->handle == 0)
-      it.m_imp.reset(); // eof, so make end iterator
-    else // not eof
-    {
-      it.m_imp->dir_entry.assign(p / filename, file_stat, symlink_file_stat);
-      if (filename[0] == dot // dot or dot-dot
-        && (filename.size()== 1
-          || (filename[1] == dot
-            && filename.size()== 2)))
-        {  it.increment(*ec); }
-    }
-  }
+  boost::scoped_array<wchar_t> big_buf(new wchar_t[len]);
 
-  void directory_iterator_increment(directory_iterator& it,
-    system::error_code* ec)
-  {
-    BOOST_ASSERT_MSG(it.m_imp.get(), "attempt to increment end iterator");
-    BOOST_ASSERT_MSG(it.m_imp->handle != 0, "internal program error");
-    
-    path::string_type filename;
-    file_status file_stat, symlink_file_stat;
-    system::error_code temp_ec;
-
-    for (;;)
-    {
-      temp_ec = dir_itr_increment(it.m_imp->handle,
-#       if defined(BOOST_POSIX_API)
-        it.m_imp->buffer,
-#       endif
-        filename, file_stat, symlink_file_stat);
+  return error(get_full_path_name(p, len , big_buf.get(), &pfn)== 0 ? BOOST_ERRNO : 0,
+    p, ec, "boost::filesystem::system_complete")
+    ? path()
+    : path(big_buf.get());
+# endif
+}
 
-      if (temp_ec)  // happens if filesystem is corrupt, such as on a damaged optical disc
-      {
-        path error_path(it.m_imp->dir_entry.path().parent_path());  // fix ticket #5900
-        it.m_imp.reset();
-        if (ec == 0)
-          BOOST_FILESYSTEM_THROW(
-            filesystem_error("boost::filesystem::directory_iterator::operator++",
-              error_path,
-              error_code(BOOST_ERRNO, system_category())));
-        ec->assign(BOOST_ERRNO, system_category());
-        return;
-      }
-      else if (ec != 0) ec->clear();
+BOOST_FILESYSTEM_DECL
+path weakly_canonical(const path& p, system::error_code* ec)
+{
+  path head(p);
+  path tail;
+  system::error_code tmp_ec;
+  path::iterator itr = p.end();
 
-      if (it.m_imp->handle == 0)  // eof, make end
-      {
-        it.m_imp.reset();
-        return;
-      }
+  for (; !head.empty(); --itr)
+  {
+    file_status head_status = status(head, tmp_ec);
+    if (error(head_status.type() == fs::status_error,
+      head, ec, "boost::filesystem::weakly_canonical"))
+      return path();
+    if (head_status.type() != fs::file_not_found)
+      break;
+    head.remove_filename();
+  }
+
+  bool tail_has_dots = false;
+  for (; itr != p.end(); ++itr)
+  {
+    tail /= *itr;
+    // for a later optimization, track if any dot or dot-dot elements are present
+    if (itr->native().size() <= 2
+      && itr->native()[0] == dot
+      && (itr->native().size() == 1 || itr->native()[1] == dot))
+      tail_has_dots = true;
+  }
+
+  if (head.empty())
+    return p.lexically_normal();
+  head = canonical(head, tmp_ec);
+  if (error(tmp_ec.value(), head, ec, "boost::filesystem::weakly_canonical"))
+    return path();
+  return tail.empty()
+    ? head
+    : (tail_has_dots  // optimization: only normalize if tail had dot or dot-dot element
+        ? (head/tail).lexically_normal()
+        : head/tail);
+}
 
-      if (!(filename[0] == dot // !(dot or dot-dot)
-        && (filename.size()== 1
-          || (filename[1] == dot
-            && filename.size()== 2))))
-      {
-        it.m_imp->dir_entry.replace_filename(
-          filename, file_stat, symlink_file_stat);
-        return;
-      }
-    }
-  }
-}  // namespace detail
+} // namespace detail
 } // namespace filesystem
 } // namespace boost