BVB Source Codes

mars Show operations.cpp Source code

Return Download mars: download operations.cpp Source code - Download mars Source code - Type:.cpp
  1. //  operations.cpp  --------------------------------------------------------------------//
  2.  
  3. //  Copyright 2002-2009, 2014 Beman Dawes
  4. //  Copyright 2001 Dietmar Kuehl
  5.  
  6. //  Distributed under the Boost Software License, Version 1.0.
  7. //  See http://www.boost.org/LICENSE_1_0.txt
  8.  
  9. //  See library home page at http://www.boost.org/libs/filesystem
  10.  
  11. //--------------------------------------------------------------------------------------//
  12.  
  13. //  define 64-bit offset macros BEFORE including boost/config.hpp (see ticket #5355)
  14. #if !(defined(__HP_aCC) && defined(_ILP32) && !defined(_STATVFS_ACPP_PROBLEMS_FIXED))
  15. #define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect,
  16. #endif
  17. #if !defined(__PGI)
  18. #define __USE_FILE_OFFSET64 // but that is harmless on Windows and on POSIX
  19.       // 64-bit systems or on 32-bit systems which don't have files larger
  20.       // than can be represented by a traditional POSIX/UNIX off_t type.
  21.       // OTOH, defining them should kick in 64-bit off_t's (and thus
  22.       // st_size)on 32-bit systems that provide the Large File
  23.       // Support (LFS)interface, such as Linux, Solaris, and IRIX.
  24.       // The defines are given before any headers are included to
  25.       // ensure that they are available to all included headers.
  26.       // That is required at least on Solaris, and possibly on other
  27.       // systems as well.
  28. #else
  29. #define _FILE_OFFSET_BITS 64
  30. #endif
  31.  
  32. // define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows
  33. // the library is being built (possibly exporting rather than importing code)
  34. #define BOOST_FILESYSTEM_SOURCE
  35.  
  36. #ifndef BOOST_SYSTEM_NO_DEPRECATED
  37. # define BOOST_SYSTEM_NO_DEPRECATED
  38. #endif
  39.  
  40. #ifndef _POSIX_PTHREAD_SEMANTICS
  41. # define _POSIX_PTHREAD_SEMANTICS  // Sun readdir_r()needs this
  42. #endif
  43.  
  44. #include <boost/filesystem/operations.hpp>
  45. #include <boost/scoped_array.hpp>
  46. #include <boost/detail/workaround.hpp>
  47. #include <vector>
  48. #include <cstdlib>     // for malloc, free
  49. #include <cstring>
  50. #include <cstdio>      // for remove, rename
  51. #if defined(__QNXNTO__)  // see ticket #5355
  52. # include <stdio.h>
  53. #endif
  54. #include <cerrno>
  55.  
  56. #ifdef BOOST_FILEYSTEM_INCLUDE_IOSTREAM
  57. # include <iostream>
  58. #endif
  59.  
  60. namespace fs = mars_boost::filesystem;
  61. using mars_boost::filesystem::path;
  62. using mars_boost::filesystem::filesystem_error;
  63. using mars_boost::filesystem::perms;
  64. using mars_boost::system::error_code;
  65. using mars_boost::system::error_category;
  66. using mars_boost::system::system_category;
  67. using std::string;
  68. using std::wstring;
  69.  
  70. # ifdef BOOST_POSIX_API
  71.  
  72. #   include <sys/types.h>
  73. #   include <sys/stat.h>
  74. #   if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) \
  75.  && !defined(__VXWORKS__)
  76. #     include <sys/statvfs.h>
  77. #     define BOOST_STATVFS statvfs
  78. #     define BOOST_STATVFS_F_FRSIZE vfs.f_frsize
  79. #   else
  80. #     ifdef __OpenBSD__
  81. #       include <sys/param.h>
  82. #     elif defined(__ANDROID__)
  83. #       include <sys/vfs.h>
  84. #     endif
  85. #     if !defined(__VXWORKS__)
  86. #       include <sys/mount.h>
  87. #     endif
  88. #     define BOOST_STATVFS statfs
  89. #     define BOOST_STATVFS_F_FRSIZE static_cast<mars_boost::uintmax_t>(vfs.f_bsize)
  90. #   endif
  91. #   include <dirent.h>
  92. #   include <unistd.h>
  93. #   include <fcntl.h>
  94. #   include <utime.h>
  95. #   include "limits.h"
  96.  
  97. # else // BOOST_WINDOW_API
  98.  
  99. #   if (defined(__MINGW32__) || defined(__CYGWIN__)) && !defined(WINVER)
  100.       // Versions of MinGW or Cygwin that support Filesystem V3 support at least WINVER 0x501.
  101.       // See MinGW's windef.h
  102. #     define WINVER 0x501
  103. #   endif
  104. #   include <io.h>
  105. #   include <windows.h>
  106. #   include <winnt.h>
  107. #   if !defined(_WIN32_WINNT)
  108. #     define  _WIN32_WINNT   0x0500
  109. #   endif
  110. #   if defined(__BORLANDC__) || defined(__MWERKS__)
  111. #     if defined(__BORLANDC__)
  112.         using std::time_t;
  113. #     endif
  114. #     include <utime.h>
  115. #   else
  116. #     include <sys/utime.h>
  117. #   endif
  118.  
  119. //  REPARSE_DATA_BUFFER related definitions are found in ntifs.h, which is part of the
  120. //  Windows Device Driver Kit. Since that's inconvenient, the definitions are provided
  121. //  here. See http://msdn.microsoft.com/en-us/library/ms791514.aspx
  122.  
  123. #if !defined(REPARSE_DATA_BUFFER_HEADER_SIZE)  // mingw winnt.h does provide the defs
  124.  
  125. #define SYMLINK_FLAG_RELATIVE 1
  126.  
  127. typedef struct _REPARSE_DATA_BUFFER {
  128.   ULONG  ReparseTag;
  129.   USHORT  ReparseDataLength;
  130.   USHORT  Reserved;
  131.   union {
  132.     struct {
  133.       USHORT  SubstituteNameOffset;
  134.       USHORT  SubstituteNameLength;
  135.       USHORT  PrintNameOffset;
  136.       USHORT  PrintNameLength;
  137.       ULONG  Flags;
  138.       WCHAR  PathBuffer[1];
  139.   /*  Example of distinction between substitute and print names:
  140.         mklink /d ldrive c:\
  141.         SubstituteName: c:\\??\
  142.         PrintName: c:\
  143.   */
  144.      } SymbolicLinkReparseBuffer;
  145.     struct {
  146.       USHORT  SubstituteNameOffset;
  147.       USHORT  SubstituteNameLength;
  148.       USHORT  PrintNameOffset;
  149.       USHORT  PrintNameLength;
  150.       WCHAR  PathBuffer[1];
  151.       } MountPointReparseBuffer;
  152.     struct {
  153.       UCHAR  DataBuffer[1];
  154.     } GenericReparseBuffer;
  155.   };
  156. } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
  157.  
  158. #define REPARSE_DATA_BUFFER_HEADER_SIZE \
  159.   FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer)
  160.  
  161. #endif
  162.  
  163. #ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
  164. #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE  ( 16 * 1024 )
  165. #endif
  166.  
  167. # ifndef FSCTL_GET_REPARSE_POINT
  168. #   define FSCTL_GET_REPARSE_POINT 0x900a8
  169. # endif
  170.  
  171. # ifndef IO_REPARSE_TAG_SYMLINK
  172. #   define IO_REPARSE_TAG_SYMLINK (0xA000000CL)      
  173. # endif
  174.  
  175. inline std::wstring wgetenv(const wchar_t* name)
  176. {
  177.   // use vector since for C++03 basic_string is not required to be contiguous
  178.   std::vector<wchar_t> buf(::GetEnvironmentVariableW(name, NULL, 0));
  179.  
  180.   // C++03 vector does not have data() so use &buf[0]
  181.   return (buf.empty()
  182.     || ::GetEnvironmentVariableW(name, &buf[0], static_cast<DWORD>(buf.size())) == 0)
  183.     ? std::wstring() : std::wstring(&buf[0]);
  184. }
  185.  
  186. # endif  // BOOST_WINDOWS_API
  187.  
  188. //  BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in
  189. //  dir_itr_increment. The config tests are placed here because some of the
  190. //  macros being tested come from dirent.h.
  191. //
  192. // TODO: find out what macros indicate dirent::d_type present in more libraries
  193. # if defined(BOOST_WINDOWS_API)\
  194.   || defined(_DIRENT_HAVE_D_TYPE)// defined by GNU C library if d_type present
  195. #   define BOOST_FILESYSTEM_STATUS_CACHE
  196. # endif
  197.  
  198. //  POSIX/Windows macros  ----------------------------------------------------//
  199.  
  200. //  Portions of the POSIX and Windows API's are very similar, except for name,
  201. //  order of arguments, and meaning of zero/non-zero returns. The macros below
  202. //  abstract away those differences. They follow Windows naming and order of
  203. //  arguments, and return true to indicate no error occurred. [POSIX naming,
  204. //  order of arguments, and meaning of return were followed initially, but
  205. //  found to be less clear and cause more coding errors.]
  206.  
  207. # if defined(BOOST_POSIX_API)
  208.  
  209. typedef int err_t;
  210.  
  211. //  POSIX uses a 0 return to indicate success
  212. #   define BOOST_ERRNO    errno
  213. #   define BOOST_SET_CURRENT_DIRECTORY(P)(::chdir(P)== 0)
  214. #   define BOOST_CREATE_DIRECTORY(P)(::mkdir(P, S_IRWXU|S_IRWXG|S_IRWXO)== 0)
  215. #   define BOOST_CREATE_HARD_LINK(F,T)(::link(T, F)== 0)
  216. #   define BOOST_CREATE_SYMBOLIC_LINK(F,T,Flag)(::symlink(T, F)== 0)
  217. #   define BOOST_REMOVE_DIRECTORY(P)(::rmdir(P)== 0)
  218. #   define BOOST_DELETE_FILE(P)(::unlink(P)== 0)
  219. #   define BOOST_COPY_DIRECTORY(F,T)(!(::stat(from.c_str(), &from_stat)!= 0\
  220.          || ::mkdir(to.c_str(),from_stat.st_mode)!= 0))
  221. #   define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool)
  222. #   define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0)
  223. #   define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0)
  224.  
  225. #   define BOOST_ERROR_NOT_SUPPORTED ENOSYS
  226. #   define BOOST_ERROR_ALREADY_EXISTS EEXIST
  227.  
  228. # else  // BOOST_WINDOWS_API
  229.  
  230. typedef DWORD err_t;
  231.  
  232. //  Windows uses a non-0 return to indicate success
  233. #   define BOOST_ERRNO    ::GetLastError()
  234. #   define BOOST_SET_CURRENT_DIRECTORY(P)(::SetCurrentDirectoryW(P)!= 0)
  235. #   define BOOST_CREATE_DIRECTORY(P)(::CreateDirectoryW(P, 0)!= 0)
  236. #   define BOOST_CREATE_HARD_LINK(F,T)(create_hard_link_api(F, T, 0)!= 0)
  237. #   define BOOST_CREATE_SYMBOLIC_LINK(F,T,Flag)(create_symbolic_link_api(F, T, Flag)!= 0)
  238. #   define BOOST_REMOVE_DIRECTORY(P)(::RemoveDirectoryW(P)!= 0)
  239. #   define BOOST_DELETE_FILE(P)(::DeleteFileW(P)!= 0)
  240. #   define BOOST_COPY_DIRECTORY(F,T)(::CreateDirectoryExW(F, T, 0)!= 0)
  241. #   define BOOST_COPY_FILE(F,T,FailIfExistsBool)(::CopyFileW(F, T, FailIfExistsBool)!= 0)
  242. #   define BOOST_MOVE_FILE(OLD,NEW)(::MoveFileExW(OLD, NEW, MOVEFILE_REPLACE_EXISTING|MOVEFILE_COPY_ALLOWED)!= 0)
  243. #   define BOOST_RESIZE_FILE(P,SZ)(resize_file_api(P, SZ)!= 0)
  244. #   define BOOST_READ_SYMLINK(P,T)
  245.  
  246. #   define BOOST_ERROR_ALREADY_EXISTS ERROR_ALREADY_EXISTS
  247. #   define BOOST_ERROR_NOT_SUPPORTED ERROR_NOT_SUPPORTED
  248.  
  249. # endif
  250.  
  251. //--------------------------------------------------------------------------------------//
  252. //                                                                                      //
  253. //                        helpers (all operating systems)                               //
  254. //                                                                                      //
  255. //--------------------------------------------------------------------------------------//
  256.  
  257. namespace
  258. {
  259.  
  260.   fs::file_type query_file_type(const path& p, error_code* ec);
  261.  
  262.   mars_boost::filesystem::directory_iterator end_dir_itr;
  263.  
  264.   //  error handling helpers  ----------------------------------------------------------//
  265.  
  266.   bool error(err_t error_num, error_code* ec, const char* message);
  267.   bool error(err_t error_num, const path& p, error_code* ec, const char* message);
  268.   bool error(err_t error_num, const path& p1, const path& p2, error_code* ec,
  269.     const char* message);
  270.  
  271.   const error_code ok;
  272.  
  273.   //  error_num is value of errno on POSIX, error code (from ::GetLastError()) on Windows.
  274.   //  Interface changed 30 Jan 15 to have caller supply error_num as ::SetLastError()
  275.   //  values were apparently getting cleared before they could be retrieved by error().
  276.  
  277.   bool error(err_t error_num, error_code* ec, const char* message)
  278.   {
  279.     if (!error_num)
  280.     {
  281.       if (ec != 0) ec->clear();
  282.     }
  283.     else  
  284.     { //  error
  285.       if (ec == 0)
  286.         BOOST_FILESYSTEM_THROW(filesystem_error(message,
  287.           error_code(error_num, system_category())));
  288.       else
  289.         ec->assign(error_num, system_category());
  290.     }
  291.     return error_num != 0;
  292.   }
  293.  
  294.   bool error(err_t error_num, const path& p, error_code* ec, const char* message)
  295.   {
  296.     if (!error_num)
  297.     {
  298.       if (ec != 0) ec->clear();
  299.     }
  300.     else  
  301.     { //  error
  302.       if (ec == 0)
  303.         BOOST_FILESYSTEM_THROW(filesystem_error(message,
  304.           p, error_code(error_num, system_category())));
  305.       else
  306.         ec->assign(error_num, system_category());
  307.     }
  308.     return error_num != 0;
  309.   }
  310.  
  311.   bool error(err_t error_num, const path& p1, const path& p2, error_code* ec,
  312.     const char* message)
  313.   {
  314.     if (!error_num)
  315.     {
  316.       if (ec != 0) ec->clear();
  317.     }
  318.     else  
  319.     { //  error
  320.       if (ec == 0)
  321.         BOOST_FILESYSTEM_THROW(filesystem_error(message,
  322.           p1, p2, error_code(error_num, system_category())));
  323.       else
  324.         ec->assign(error_num, system_category());
  325.     }
  326.     return error_num != 0;
  327.   }
  328.  
  329.   //  general helpers  -----------------------------------------------------------------//
  330.  
  331.   bool is_empty_directory(const path& p)
  332.   {
  333.     return fs::directory_iterator(p)== end_dir_itr;
  334.   }
  335.  
  336.   bool not_found_error(int errval); // forward declaration
  337.  
  338.   // only called if directory exists
  339.   bool remove_directory(const path& p) // true if succeeds or not found
  340.   {
  341.     return BOOST_REMOVE_DIRECTORY(p.c_str())
  342.       || not_found_error(BOOST_ERRNO);  // mitigate possible file system race. See #11166
  343.   }
  344.  
  345.   // only called if file exists
  346.   bool remove_file(const path& p) // true if succeeds or not found
  347.   {
  348.     return BOOST_DELETE_FILE(p.c_str())
  349.       || not_found_error(BOOST_ERRNO);  // mitigate possible file system race. See #11166
  350.   }
  351.  
  352.   // called by remove and remove_all_aux
  353.   bool remove_file_or_directory(const path& p, fs::file_type type, error_code* ec)
  354.     // return true if file removed, false if not removed
  355.   {
  356.     if (type == fs::file_not_found)
  357.     {
  358.       if (ec != 0) ec->clear();
  359.       return false;
  360.     }
  361.  
  362.     if (type == fs::directory_file
  363. #     ifdef BOOST_WINDOWS_API
  364.         || type == fs::_detail_directory_symlink
  365. #     endif
  366.       )
  367.     {
  368.       if (error(!remove_directory(p) ? BOOST_ERRNO : 0, p, ec,
  369.         "mars_boost::filesystem::remove"))
  370.           return false;
  371.     }
  372.     else
  373.     {
  374.       if (error(!remove_file(p) ? BOOST_ERRNO : 0, p, ec,
  375.         "mars_boost::filesystem::remove"))
  376.           return false;
  377.     }
  378.     return true;
  379.   }
  380.  
  381.   mars_boost::uintmax_t remove_all_aux(const path& p, fs::file_type type,
  382.     error_code* ec)
  383.   {
  384.     mars_boost::uintmax_t count = 1;
  385.  
  386.     if (type == fs::directory_file)  // but not a directory symlink
  387.     {
  388.       for (fs::directory_iterator itr(p);
  389.             itr != end_dir_itr; ++itr)
  390.       {
  391.         fs::file_type tmp_type = query_file_type(itr->path(), ec);
  392.         if (ec != 0 && *ec)
  393.           return count;
  394.         count += remove_all_aux(itr->path(), tmp_type, ec);
  395.       }
  396.     }
  397.     remove_file_or_directory(p, type, ec);
  398.     return count;
  399.   }
  400.  
  401. #ifdef BOOST_POSIX_API
  402.  
  403. //--------------------------------------------------------------------------------------//
  404. //                                                                                      //
  405. //                            POSIX-specific helpers                                    //
  406. //                                                                                      //
  407. //--------------------------------------------------------------------------------------//
  408.  
  409.   const char dot = '.';
  410.  
  411.   bool not_found_error(int errval)
  412.   {
  413.     return errno == ENOENT || errno == ENOTDIR;
  414.   }
  415.  
  416.   bool // true if ok
  417.   copy_file_api(const std::string& from_p,
  418.     const std::string& to_p, bool fail_if_exists)
  419.   {
  420.     const std::size_t buf_sz = 32768;
  421.     mars_boost::scoped_array<char> buf(new char [buf_sz]);
  422.     int infile=-1, outfile=-1;  // -1 means not open
  423.  
  424.     // bug fixed: code previously did a stat()on the from_file first, but that
  425.     // introduced a gratuitous race condition; the stat()is now done after the open()
  426.  
  427.     if ((infile = ::open(from_p.c_str(), O_RDONLY))< 0)
  428.       { return false; }
  429.  
  430.     struct stat from_stat;
  431.     if (::stat(from_p.c_str(), &from_stat)!= 0)
  432.     {
  433.       ::close(infile);
  434.       return false;
  435.     }
  436.  
  437.     int oflag = O_CREAT | O_WRONLY | O_TRUNC;
  438.     if (fail_if_exists)
  439.       oflag |= O_EXCL;
  440.     if ((outfile = ::open(to_p.c_str(), oflag, from_stat.st_mode))< 0)
  441.     {
  442.       int open_errno = errno;
  443.       BOOST_ASSERT(infile >= 0);
  444.       ::close(infile);
  445.       errno = open_errno;
  446.       return false;
  447.     }
  448.  
  449.     ssize_t sz, sz_read=1, sz_write;
  450.     while (sz_read > 0
  451.       && (sz_read = ::read(infile, buf.get(), buf_sz)) > 0)
  452.     {
  453.       // Allow for partial writes - see Advanced Unix Programming (2nd Ed.),
  454.       // Marc Rochkind, Addison-Wesley, 2004, page 94
  455.       sz_write = 0;
  456.       do
  457.       {
  458.         BOOST_ASSERT(sz_read - sz_write > 0);  // #1
  459.           // ticket 4438 claimed possible infinite loop if write returns 0. My analysis
  460.           // is that POSIX specifies 0 return only if 3rd arg is 0, and that will never
  461.           // happen due to loop entry and coninuation conditions. BOOST_ASSERT #1 above
  462.           // and #2 below added to verify that analysis.
  463.         if ((sz = ::write(outfile, buf.get() + sz_write,
  464.           sz_read - sz_write)) < 0)
  465.         {
  466.           sz_read = sz; // cause read loop termination
  467.           break;        //  and error reported after closes
  468.         }
  469.         BOOST_ASSERT(sz > 0);                  // #2
  470.         sz_write += sz;
  471.       } while (sz_write < sz_read);
  472.     }
  473.  
  474.     if (::close(infile)< 0)
  475.       sz_read = -1;
  476.     if (::close(outfile)< 0)
  477.       sz_read = -1;
  478.  
  479.     return sz_read >= 0;
  480.   }
  481.  
  482.   inline fs::file_type query_file_type(const path& p, error_code* ec)
  483.   {
  484.     return fs::detail::symlink_status(p, ec).type();
  485.   }
  486.  
  487. # else
  488.  
  489. //--------------------------------------------------------------------------------------//
  490. //                                                                                      //
  491. //                            Windows-specific helpers                                  //
  492. //                                                                                      //
  493. //--------------------------------------------------------------------------------------//
  494.  
  495.   const std::size_t buf_size=128;
  496.  
  497.   const wchar_t dot = L'.';
  498.  
  499.   bool not_found_error(int errval)
  500.   {
  501.     return errval == ERROR_FILE_NOT_FOUND
  502.       || errval == ERROR_PATH_NOT_FOUND
  503.       || errval == ERROR_INVALID_NAME  // "tools/jam/src/:sys:stat.h", "//foo"
  504.       || errval == ERROR_INVALID_DRIVE  // USB card reader with no card inserted
  505.       || errval == ERROR_NOT_READY  // CD/DVD drive with no disc inserted
  506.       || errval == ERROR_INVALID_PARAMETER  // ":sys:stat.h"
  507.       || errval == ERROR_BAD_PATHNAME  // "//nosuch" on Win64
  508.       || errval == ERROR_BAD_NETPATH;  // "//nosuch" on Win32
  509.   }
  510.  
  511. // some distributions of mingw as early as GLIBCXX__ 20110325 have _stricmp, but the
  512. // offical 4.6.2 release with __GLIBCXX__ 20111026  doesn't. Play it safe for now, and
  513. // only use _stricmp if _MSC_VER is defined
  514. #if defined(_MSC_VER) // || (defined(__GLIBCXX__) && __GLIBCXX__ >= 20110325)
  515. #  define BOOST_FILESYSTEM_STRICMP _stricmp
  516. #else
  517. #  define BOOST_FILESYSTEM_STRICMP strcmp
  518. #endif
  519.  
  520.   perms make_permissions(const path& p, DWORD attr)
  521.   {
  522.     perms prms = fs::owner_read | fs::group_read | fs::others_read;
  523.     if  ((attr & FILE_ATTRIBUTE_READONLY) == 0)
  524.       prms |= fs::owner_write | fs::group_write | fs::others_write;
  525.     if (BOOST_FILESYSTEM_STRICMP(p.extension().string().c_str(), ".exe") == 0
  526.       || BOOST_FILESYSTEM_STRICMP(p.extension().string().c_str(), ".com") == 0
  527.       || BOOST_FILESYSTEM_STRICMP(p.extension().string().c_str(), ".bat") == 0
  528.       || BOOST_FILESYSTEM_STRICMP(p.extension().string().c_str(), ".cmd") == 0)
  529.       prms |= fs::owner_exe | fs::group_exe | fs::others_exe;
  530.     return prms;
  531.   }
  532.  
  533.   // these constants come from inspecting some Microsoft sample code
  534.   std::time_t to_time_t(const FILETIME & ft)
  535.   {
  536.     __int64 t = (static_cast<__int64>(ft.dwHighDateTime)<< 32)
  537.       + ft.dwLowDateTime;
  538. #   if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // > VC++ 7.0
  539.     t -= 116444736000000000LL;
  540. #   else
  541.     t -= 116444736000000000;
  542. #   endif
  543.     t /= 10000000;
  544.     return static_cast<std::time_t>(t);
  545.   }
  546.  
  547.   void to_FILETIME(std::time_t t, FILETIME & ft)
  548.   {
  549.     __int64 temp = t;
  550.     temp *= 10000000;
  551. #   if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // > VC++ 7.0
  552.     temp += 116444736000000000LL;
  553. #   else
  554.     temp += 116444736000000000;
  555. #   endif
  556.     ft.dwLowDateTime = static_cast<DWORD>(temp);
  557.     ft.dwHighDateTime = static_cast<DWORD>(temp >> 32);
  558.   }
  559.  
  560.   // Thanks to Jeremy Maitin-Shepard for much help and for permission to
  561.   // base the equivalent()implementation on portions of his
  562.   // file-equivalence-win32.cpp experimental code.
  563.  
  564.   struct handle_wrapper
  565.   {
  566.     HANDLE handle;
  567.     handle_wrapper(HANDLE h)
  568.       : handle(h){}
  569.     ~handle_wrapper()
  570.     {
  571.       if (handle != INVALID_HANDLE_VALUE)
  572.         ::CloseHandle(handle);
  573.     }
  574.   };
  575.  
  576.   HANDLE create_file_handle(const path& p, DWORD dwDesiredAccess,
  577.     DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  578.     DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
  579.     HANDLE hTemplateFile)
  580.   {
  581.     return ::CreateFileW(p.c_str(), dwDesiredAccess, dwShareMode,
  582.       lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
  583.       hTemplateFile);
  584.   }
  585.  
  586.   bool is_reparse_point_a_symlink(const path& p)
  587.   {
  588.     handle_wrapper h(create_file_handle(p, FILE_READ_EA,
  589.       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
  590.       FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL));
  591.     if (h.handle == INVALID_HANDLE_VALUE)
  592.       return false;
  593.  
  594.     mars_boost::scoped_array<char> buf(new char [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);    
  595.  
  596.     // Query the reparse data
  597.     DWORD dwRetLen;
  598.     BOOL result = ::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buf.get(),
  599.       MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dwRetLen, NULL);
  600.     if (!result) return false;
  601.  
  602.     return reinterpret_cast<const REPARSE_DATA_BUFFER*>(buf.get())->ReparseTag
  603.         == IO_REPARSE_TAG_SYMLINK
  604.         // Issue 9016 asked that NTFS directory junctions be recognized as directories.
  605.         // That is equivalent to recognizing them as symlinks, and then the normal symlink
  606.         // mechanism will take care of recognizing them as directories.
  607.         //
  608.         // Directory junctions are very similar to symlinks, but have some performance
  609.         // and other advantages over symlinks. They can be created from the command line
  610.         // with "mklink /j junction-name target-path".
  611.       || reinterpret_cast<const REPARSE_DATA_BUFFER*>(buf.get())->ReparseTag
  612.         == IO_REPARSE_TAG_MOUNT_POINT;  // aka "directory junction" or "junction"
  613.   }
  614.  
  615.   inline std::size_t get_full_path_name(
  616.     const path& src, std::size_t len, wchar_t* buf, wchar_t** p)
  617.   {
  618.     return static_cast<std::size_t>(
  619.       ::GetFullPathNameW(src.c_str(), static_cast<DWORD>(len), buf, p));
  620.   }
  621.  
  622.   fs::file_status process_status_failure(const path& p, error_code* ec)
  623.   {
  624.     int errval(::GetLastError());
  625.     if (ec != 0)                             // always report errval, even though some
  626.       ec->assign(errval, system_category());   // errval values are not status_errors
  627.  
  628.     if (not_found_error(errval))
  629.     {
  630.       return fs::file_status(fs::file_not_found, fs::no_perms);
  631.     }
  632.     else if ((errval == ERROR_SHARING_VIOLATION))
  633.     {
  634.       return fs::file_status(fs::type_unknown);
  635.     }
  636.     if (ec == 0)
  637.       BOOST_FILESYSTEM_THROW(filesystem_error("mars_boost::filesystem::status",
  638.         p, error_code(errval, system_category())));
  639.     return fs::file_status(fs::status_error);
  640.   }
  641.  
  642.   //  differs from symlink_status() in that directory symlinks are reported as
  643.   //  _detail_directory_symlink, as required on Windows by remove() and its helpers.
  644.   fs::file_type query_file_type(const path& p, error_code* ec)
  645.   {
  646.     DWORD attr(::GetFileAttributesW(p.c_str()));
  647.     if (attr == 0xFFFFFFFF)
  648.     {
  649.       return process_status_failure(p, ec).type();
  650.     }
  651.  
  652.     if (ec != 0) ec->clear();
  653.  
  654.     if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
  655.     {
  656.       if (is_reparse_point_a_symlink(p))
  657.         return (attr & FILE_ATTRIBUTE_DIRECTORY)
  658.           ? fs::_detail_directory_symlink
  659.           : fs::symlink_file;
  660.       return fs::reparse_file;
  661.     }
  662.  
  663.     return (attr & FILE_ATTRIBUTE_DIRECTORY)
  664.       ? fs::directory_file
  665.       : fs::regular_file;
  666.   }
  667.  
  668.   BOOL resize_file_api(const wchar_t* p, mars_boost::uintmax_t size)
  669.   {
  670.     handle_wrapper h(CreateFileW(p, GENERIC_WRITE, 0, 0, OPEN_EXISTING,
  671.                                 FILE_ATTRIBUTE_NORMAL, 0));
  672.     LARGE_INTEGER sz;
  673.     sz.QuadPart = size;
  674.     return h.handle != INVALID_HANDLE_VALUE
  675.       && ::SetFilePointerEx(h.handle, sz, 0, FILE_BEGIN)
  676.       && ::SetEndOfFile(h.handle);
  677.   }
  678.  
  679.   //  Windows kernel32.dll functions that may or may not be present
  680.   //  must be accessed through pointers
  681.  
  682.   typedef BOOL (WINAPI *PtrCreateHardLinkW)(
  683.     /*__in*/       LPCWSTR lpFileName,
  684.     /*__in*/       LPCWSTR lpExistingFileName,
  685.     /*__reserved*/ LPSECURITY_ATTRIBUTES lpSecurityAttributes
  686.    );
  687.  
  688.   PtrCreateHardLinkW create_hard_link_api = PtrCreateHardLinkW(
  689.     ::GetProcAddress(
  690.       ::GetModuleHandle(TEXT("kernel32.dll")), "CreateHardLinkW"));
  691.  
  692.   typedef BOOLEAN (WINAPI *PtrCreateSymbolicLinkW)(
  693.     /*__in*/ LPCWSTR lpSymlinkFileName,
  694.     /*__in*/ LPCWSTR lpTargetFileName,
  695.     /*__in*/ DWORD dwFlags
  696.    );
  697.  
  698.   PtrCreateSymbolicLinkW create_symbolic_link_api = PtrCreateSymbolicLinkW(
  699.     ::GetProcAddress(
  700.       ::GetModuleHandle(TEXT("kernel32.dll")), "CreateSymbolicLinkW"));
  701.  
  702. #endif
  703.  
  704. //#ifdef BOOST_WINDOWS_API
  705. //
  706. //
  707. //  inline bool get_free_disk_space(const std::wstring& ph,
  708. //    PULARGE_INTEGER avail, PULARGE_INTEGER total, PULARGE_INTEGER free)
  709. //    { return ::GetDiskFreeSpaceExW(ph.c_str(), avail, total, free)!= 0; }
  710. //
  711. //#endif
  712.  
  713. } // unnamed namespace
  714.  
  715. //--------------------------------------------------------------------------------------//
  716. //                                                                                      //
  717. //                operations functions declared in operations.hpp                       //
  718. //                            in alphabetic order                                       //
  719. //                                                                                      //
  720. //--------------------------------------------------------------------------------------//
  721.  
  722. namespace mars_boost {} namespace boost = mars_boost; namespace mars_boost
  723. {
  724. namespace filesystem
  725. {
  726.  
  727.   BOOST_FILESYSTEM_DECL
  728.   path absolute(const path& p, const path& base)
  729.   {
  730. //    if ( p.empty() || p.is_absolute() )
  731. //      return p;
  732. //    //  recursively calling absolute is sub-optimal, but is simple
  733. //    path abs_base(base.is_absolute() ? base : absolute(base));
  734. //# ifdef BOOST_WINDOWS_API
  735. //    if (p.has_root_directory())
  736. //      return abs_base.root_name() / p;
  737. //    //  !p.has_root_directory
  738. //    if (p.has_root_name())
  739. //      return p.root_name()
  740. //        / abs_base.root_directory() / abs_base.relative_path() / p.relative_path();
  741. //    //  !p.has_root_name()
  742. //# endif
  743. //    return abs_base / p;
  744.  
  745.     //  recursively calling absolute is sub-optimal, but is sure and simple
  746.     path abs_base(base.is_absolute() ? base : absolute(base));
  747.  
  748.     //  store expensive to compute values that are needed multiple times
  749.     path p_root_name (p.root_name());
  750.     path base_root_name (abs_base.root_name());
  751.     path p_root_directory (p.root_directory());
  752.  
  753.     if (p.empty())
  754.       return abs_base;
  755.  
  756.     if (!p_root_name.empty())  // p.has_root_name()
  757.     {
  758.       if (p_root_directory.empty())  // !p.has_root_directory()
  759.         return p_root_name / abs_base.root_directory()
  760.         / abs_base.relative_path() / p.relative_path();
  761.       // p is absolute, so fall through to return p at end of block
  762.     }
  763.  
  764.     else if (!p_root_directory.empty())  // p.has_root_directory()
  765.     {
  766. #     ifdef BOOST_POSIX_API
  767.       // POSIX can have root name it it is a network path
  768.       if (base_root_name.empty())   // !abs_base.has_root_name()
  769.         return p;
  770. #     endif
  771.       return base_root_name / p;
  772.     }
  773.  
  774.     else
  775.     {
  776.       return abs_base / p;
  777.     }
  778.  
  779.     return p;  // p.is_absolute() is true
  780.   }
  781.  
  782. namespace detail
  783. {
  784.   BOOST_FILESYSTEM_DECL bool possible_large_file_size_support()
  785.   {
  786. #   ifdef BOOST_POSIX_API
  787.     struct stat lcl_stat;
  788.     return sizeof(lcl_stat.st_size)> 4;
  789. #   else
  790.     return true;
  791. #   endif
  792.   }
  793.  
  794.   BOOST_FILESYSTEM_DECL
  795.   path canonical(const path& p, const path& base, system::error_code* ec)
  796.   {
  797.     path source (p.is_absolute() ? p : absolute(p, base));
  798.     path root(source.root_path());
  799.     path result;
  800.  
  801.     system::error_code local_ec;
  802.     file_status stat (status(source, local_ec));
  803.  
  804.     if (stat.type() == fs::file_not_found)
  805.     {
  806.       if (ec == 0)
  807.         BOOST_FILESYSTEM_THROW(filesystem_error(
  808.           "mars_boost::filesystem::canonical", source,
  809.           error_code(system::errc::no_such_file_or_directory, system::generic_category())));
  810.       else
  811.           ec->assign(system::errc::no_such_file_or_directory, system::generic_category());
  812.       return result;
  813.     }
  814.     else if (local_ec)
  815.     {
  816.       if (ec == 0)
  817.         BOOST_FILESYSTEM_THROW(filesystem_error(
  818.           "mars_boost::filesystem::canonical", source, local_ec));
  819.       *ec = local_ec;
  820.       return result;
  821.     }
  822.  
  823.     bool scan (true);
  824.     while (scan)
  825.     {
  826.       scan = false;
  827.       result.clear();
  828.       for (path::iterator itr = source.begin(); itr != source.end(); ++itr)
  829.       {
  830.         if (*itr == dot_path())
  831.           continue;
  832.         if (*itr == dot_dot_path())
  833.         {
  834.           if (result != root)
  835.             result.remove_filename();
  836.           continue;
  837.         }
  838.  
  839.         result /= *itr;
  840.  
  841.         bool is_sym (is_symlink(detail::symlink_status(result, ec)));
  842.         if (ec && *ec)
  843.           return path();
  844.  
  845.         if (is_sym)
  846.         {
  847.           path link(detail::read_symlink(result, ec));
  848.           if (ec && *ec)
  849.             return path();
  850.           result.remove_filename();
  851.  
  852.           if (link.is_absolute())
  853.           {
  854.             for (++itr; itr != source.end(); ++itr)
  855.               link /= *itr;
  856.             source = link;
  857.           }
  858.           else // link is relative
  859.           {
  860.             path new_source(result);
  861.             new_source /= link;
  862.             for (++itr; itr != source.end(); ++itr)
  863.               new_source /= *itr;
  864.             source = new_source;
  865.           }
  866.           scan = true;  // symlink causes scan to be restarted
  867.           break;
  868.         }
  869.       }
  870.     }
  871.     if (ec != 0)
  872.       ec->clear();
  873.     BOOST_ASSERT_MSG(result.is_absolute(), "canonical() implementation error; please report");
  874.     return result;
  875.   }
  876.  
  877.   BOOST_FILESYSTEM_DECL
  878.   void copy(const path& from, const path& to, system::error_code* ec)
  879.   {
  880.     file_status s(symlink_status(from, *ec));
  881.     if (ec != 0 && *ec) return;
  882.  
  883.     if(is_symlink(s))
  884.     {
  885.       copy_symlink(from, to, *ec);
  886.     }
  887.     else if(is_directory(s))
  888.     {
  889.       copy_directory(from, to, *ec);
  890.     }
  891.     else if(is_regular_file(s))
  892.     {
  893.       copy_file(from, to, fs::copy_option::fail_if_exists, *ec);
  894.     }
  895.     else
  896.     {
  897.       if (ec == 0)
  898.         BOOST_FILESYSTEM_THROW(filesystem_error("mars_boost::filesystem::copy",
  899.           from, to, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category())));
  900.       else
  901.         ec->assign(BOOST_ERROR_NOT_SUPPORTED, system_category());
  902.     }
  903.   }
  904.  
  905.   BOOST_FILESYSTEM_DECL
  906.   void copy_directory(const path& from, const path& to, system::error_code* ec)
  907.   {
  908. #   ifdef BOOST_POSIX_API
  909.     struct stat from_stat;
  910. #   endif
  911.     error(!BOOST_COPY_DIRECTORY(from.c_str(), to.c_str()) ? BOOST_ERRNO : 0,
  912.       from, to, ec, "mars_boost::filesystem::copy_directory");
  913.   }
  914.  
  915.   BOOST_FILESYSTEM_DECL
  916.   void copy_file(const path& from, const path& to, copy_option option, error_code* ec)
  917.   {
  918.     error(!BOOST_COPY_FILE(from.c_str(), to.c_str(),
  919.       option == fail_if_exists) ? BOOST_ERRNO : 0,
  920.         from, to, ec, "mars_boost::filesystem::copy_file");
  921.   }
  922.  
  923.   BOOST_FILESYSTEM_DECL
  924.   void copy_symlink(const path& existing_symlink, const path& new_symlink,
  925.     system::error_code* ec)
  926.   {
  927. # if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
  928.     error(BOOST_ERROR_NOT_SUPPORTED, new_symlink, existing_symlink, ec,
  929.       "mars_boost::filesystem::copy_symlink");
  930.  
  931. # else  // modern Windows or BOOST_POSIX_API
  932.     path p(read_symlink(existing_symlink, ec));
  933.     if (ec != 0 && *ec) return;
  934.     create_symlink(p, new_symlink, ec);
  935.  
  936. # endif
  937.   }
  938.  
  939.  BOOST_FILESYSTEM_DECL
  940.   bool create_directories(const path& p, system::error_code* ec)
  941.   {
  942.     path filename(p.filename());
  943.     if ((filename.native().size() == 1 && filename.native()[0] == dot)
  944.       || (filename.native().size() == 2
  945.         && filename.native()[0] == dot && filename.native()[1] == dot))
  946.       return create_directories(p.parent_path(), ec);
  947.  
  948.     error_code local_ec;
  949.     file_status p_status = status(p, local_ec);
  950.  
  951.     if (p_status.type() == directory_file)
  952.     {
  953.       if (ec != 0)
  954.         ec->clear();
  955.       return false;
  956.     }
  957.  
  958.     path parent = p.parent_path();
  959.     BOOST_ASSERT_MSG(parent != p, "internal error: p == p.parent_path()");
  960.     if (!parent.empty())
  961.     {
  962.       // determine if the parent exists
  963.       file_status parent_status = status(parent, local_ec);
  964.  
  965.       // if the parent does not exist, create the parent
  966.       if (parent_status.type() == file_not_found)
  967.       {
  968.         create_directories(parent, local_ec);
  969.         if (local_ec)
  970.         {
  971.           if (ec == 0)
  972.             BOOST_FILESYSTEM_THROW(filesystem_error(
  973.               "mars_boost::filesystem::create_directories", parent, local_ec));
  974.           else
  975.             *ec = local_ec;
  976.           return false;
  977.         }
  978.       }
  979.     }
  980.  
  981.     // create the directory
  982.     return create_directory(p, ec);
  983.   }
  984.  
  985.   BOOST_FILESYSTEM_DECL
  986.   bool create_directory(const path& p, error_code* ec)
  987.   {
  988.     if (BOOST_CREATE_DIRECTORY(p.c_str()))
  989.     {
  990.       if (ec != 0)
  991.         ec->clear();
  992.       return true;
  993.     }
  994.  
  995.     //  attempt to create directory failed
  996.     int errval(BOOST_ERRNO);  // save reason for failure
  997.     error_code dummy;
  998.     if (errval == BOOST_ERROR_ALREADY_EXISTS && is_directory(p, dummy))
  999.     {
  1000.       if (ec != 0)
  1001.         ec->clear();
  1002.       return false;
  1003.     }
  1004.  
  1005.     //  attempt to create directory failed && it doesn't already exist
  1006.     if (ec == 0)
  1007.       BOOST_FILESYSTEM_THROW(filesystem_error("mars_boost::filesystem::create_directory",
  1008.         p, error_code(errval, system_category())));
  1009.     else
  1010.       ec->assign(errval, system_category());
  1011.     return false;
  1012.   }
  1013.  
  1014.   BOOST_FILESYSTEM_DECL
  1015.   void create_directory_symlink(const path& to, const path& from,
  1016.                                  system::error_code* ec)
  1017.   {
  1018. #   if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0600  // SDK earlier than Vista and Server 2008
  1019.  
  1020.     error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec,
  1021.       "mars_boost::filesystem::create_directory_symlink");
  1022. #   else
  1023.  
  1024. #     if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0600
  1025.         // see if actually supported by Windows runtime dll
  1026.         if (error(!create_symbolic_link_api ? BOOST_ERROR_NOT_SUPPORTED : 0, to, from, ec,
  1027.             "mars_boost::filesystem::create_directory_symlink"))
  1028.           return;
  1029. #     endif
  1030.  
  1031.     error(!BOOST_CREATE_SYMBOLIC_LINK(from.c_str(), to.c_str(),
  1032.       SYMBOLIC_LINK_FLAG_DIRECTORY) ? BOOST_ERRNO : 0,
  1033.       to, from, ec, "mars_boost::filesystem::create_directory_symlink");
  1034. #   endif
  1035.   }
  1036.  
  1037.   BOOST_FILESYSTEM_DECL
  1038.   void create_hard_link(const path& to, const path& from, error_code* ec)
  1039.   {
  1040.  
  1041. #   if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0500  // SDK earlier than Win 2K
  1042.  
  1043.     error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec,
  1044.       "mars_boost::filesystem::create_hard_link");
  1045. #   else
  1046.  
  1047. #     if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0500
  1048.         // see if actually supported by Windows runtime dll
  1049.         if (error(!create_hard_link_api ? BOOST_ERROR_NOT_SUPPORTED : 0, to, from, ec,
  1050.             "mars_boost::filesystem::create_hard_link"))
  1051.           return;
  1052. #     endif
  1053.  
  1054.     error(!BOOST_CREATE_HARD_LINK(from.c_str(), to.c_str()) ? BOOST_ERRNO : 0, to, from, ec,
  1055.       "mars_boost::filesystem::create_hard_link");
  1056. #   endif
  1057.   }
  1058.  
  1059.   BOOST_FILESYSTEM_DECL
  1060.   void create_symlink(const path& to, const path& from, error_code* ec)
  1061.   {
  1062. #   if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0600  // SDK earlier than Vista and Server 2008
  1063.     error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec,
  1064.       "mars_boost::filesystem::create_directory_symlink");
  1065. #   else
  1066.  
  1067. #     if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0600
  1068.         // see if actually supported by Windows runtime dll
  1069.         if (error(!create_symbolic_link_api ? BOOST_ERROR_NOT_SUPPORTED : 0, to, from, ec,
  1070.             "mars_boost::filesystem::create_symlink"))
  1071.           return;
  1072. #     endif
  1073.  
  1074.     error(!BOOST_CREATE_SYMBOLIC_LINK(from.c_str(), to.c_str(), 0) ? BOOST_ERRNO : 0,
  1075.       to, from, ec, "mars_boost::filesystem::create_symlink");
  1076. #   endif
  1077.   }
  1078.  
  1079.   BOOST_FILESYSTEM_DECL
  1080.   path current_path(error_code* ec)
  1081.   {
  1082. #   ifdef BOOST_POSIX_API
  1083.     path cur;
  1084.     for (long path_max = 128;; path_max *=2)// loop 'til buffer large enough
  1085.     {
  1086.       mars_boost::scoped_array<char>
  1087.         buf(new char[static_cast<std::size_t>(path_max)]);
  1088.       if (::getcwd(buf.get(), static_cast<std::size_t>(path_max))== 0)
  1089.       {
  1090.         if (error(errno != ERANGE ? errno : 0
  1091.       // bug in some versions of the Metrowerks C lib on the Mac: wrong errno set
  1092. #         if defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
  1093.           && errno != 0
  1094. #         endif
  1095.           , ec, "mars_boost::filesystem::current_path"))
  1096.         {
  1097.           break;
  1098.         }
  1099.       }
  1100.       else
  1101.       {
  1102.         cur = buf.get();
  1103.         if (ec != 0) ec->clear();
  1104.         break;
  1105.       }
  1106.     }
  1107.     return cur;
  1108.  
  1109. #   else
  1110.     DWORD sz;
  1111.     if ((sz = ::GetCurrentDirectoryW(0, NULL)) == 0)sz = 1;
  1112.     mars_boost::scoped_array<path::value_type> buf(new path::value_type[sz]);
  1113.     error(::GetCurrentDirectoryW(sz, buf.get()) == 0 ? BOOST_ERRNO : 0, ec,
  1114.       "mars_boost::filesystem::current_path");
  1115.     return path(buf.get());
  1116. #   endif
  1117.   }
  1118.  
  1119.  
  1120.   BOOST_FILESYSTEM_DECL
  1121.   void current_path(const path& p, system::error_code* ec)
  1122.   {
  1123.     error(!BOOST_SET_CURRENT_DIRECTORY(p.c_str()) ? BOOST_ERRNO : 0,
  1124.       p, ec, "mars_boost::filesystem::current_path");
  1125.   }
  1126.  
  1127.   BOOST_FILESYSTEM_DECL
  1128.   bool equivalent(const path& p1, const path& p2, system::error_code* ec)
  1129.   {
  1130. #   ifdef BOOST_POSIX_API
  1131.     struct stat s2;
  1132.     int e2(::stat(p2.c_str(), &s2));
  1133.     struct stat s1;
  1134.     int e1(::stat(p1.c_str(), &s1));
  1135.  
  1136.     if (e1 != 0 || e2 != 0)
  1137.     {
  1138.       // if one is invalid and the other isn't then they aren't equivalent,
  1139.       // but if both are invalid then it is an error
  1140.       error (e1 != 0 && e2 != 0, p1, p2, ec, "mars_boost::filesystem::equivalent");
  1141.       return false;
  1142.     }
  1143.  
  1144.     // both stats now known to be valid
  1145.     return  s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino
  1146.         // According to the POSIX stat specs, "The st_ino and st_dev fields
  1147.         // taken together uniquely identify the file within the system."
  1148.         // Just to be sure, size and mod time are also checked.
  1149.         && s1.st_size == s2.st_size && s1.st_mtime == s2.st_mtime;
  1150.  
  1151. #   else  // Windows
  1152.  
  1153.     // Note well: Physical location on external media is part of the
  1154.     // equivalence criteria. If there are no open handles, physical location
  1155.     // can change due to defragmentation or other relocations. Thus handles
  1156.     // must be held open until location information for both paths has
  1157.     // been retrieved.
  1158.  
  1159.     // p2 is done first, so any error reported is for p1
  1160.     handle_wrapper h2(
  1161.       create_file_handle(
  1162.           p2.c_str(),
  1163.           0,
  1164.           FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  1165.           0,
  1166.           OPEN_EXISTING,
  1167.           FILE_FLAG_BACKUP_SEMANTICS,
  1168.           0));
  1169.  
  1170.     handle_wrapper h1(
  1171.       create_file_handle(
  1172.           p1.c_str(),
  1173.           0,
  1174.           FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  1175.           0,
  1176.           OPEN_EXISTING,
  1177.           FILE_FLAG_BACKUP_SEMANTICS,
  1178.           0));
  1179.  
  1180.     if (h1.handle == INVALID_HANDLE_VALUE
  1181.       || h2.handle == INVALID_HANDLE_VALUE)
  1182.     {
  1183.       // if one is invalid and the other isn't, then they aren't equivalent,
  1184.       // but if both are invalid then it is an error
  1185.       error((h1.handle == INVALID_HANDLE_VALUE
  1186.         && h2.handle == INVALID_HANDLE_VALUE) ? BOOST_ERROR_NOT_SUPPORTED : 0, p1, p2, ec,
  1187.           "mars_boost::filesystem::equivalent");
  1188.       return false;
  1189.     }
  1190.  
  1191.     // at this point, both handles are known to be valid
  1192.  
  1193.     BY_HANDLE_FILE_INFORMATION info1, info2;
  1194.  
  1195.     if (error(!::GetFileInformationByHandle(h1.handle, &info1) ? BOOST_ERRNO : 0,
  1196.       p1, p2, ec, "mars_boost::filesystem::equivalent"))
  1197.         return  false;
  1198.  
  1199.     if (error(!::GetFileInformationByHandle(h2.handle, &info2) ? BOOST_ERRNO : 0,
  1200.       p1, p2, ec, "mars_boost::filesystem::equivalent"))
  1201.         return  false;
  1202.  
  1203.     // In theory, volume serial numbers are sufficient to distinguish between
  1204.     // devices, but in practice VSN's are sometimes duplicated, so last write
  1205.     // time and file size are also checked.
  1206.       return
  1207.         info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
  1208.         && info1.nFileIndexHigh == info2.nFileIndexHigh
  1209.         && info1.nFileIndexLow == info2.nFileIndexLow
  1210.         && info1.nFileSizeHigh == info2.nFileSizeHigh
  1211.         && info1.nFileSizeLow == info2.nFileSizeLow
  1212.         && info1.ftLastWriteTime.dwLowDateTime
  1213.           == info2.ftLastWriteTime.dwLowDateTime
  1214.         && info1.ftLastWriteTime.dwHighDateTime
  1215.           == info2.ftLastWriteTime.dwHighDateTime;
  1216.  
  1217. #   endif
  1218.   }
  1219.  
  1220.   BOOST_FILESYSTEM_DECL
  1221.   mars_boost::uintmax_t file_size(const path& p, error_code* ec)
  1222.   {
  1223. #   ifdef BOOST_POSIX_API
  1224.  
  1225.     struct stat path_stat;
  1226.     if (error(::stat(p.c_str(), &path_stat)!= 0 ? BOOST_ERRNO : 0,
  1227.         p, ec, "mars_boost::filesystem::file_size"))
  1228.       return static_cast<mars_boost::uintmax_t>(-1);
  1229.    if (error(!S_ISREG(path_stat.st_mode) ? EPERM : 0,
  1230.         p, ec, "mars_boost::filesystem::file_size"))
  1231.       return static_cast<mars_boost::uintmax_t>(-1);
  1232.  
  1233.     return static_cast<mars_boost::uintmax_t>(path_stat.st_size);
  1234.  
  1235. #   else  // Windows
  1236.  
  1237.     // assume uintmax_t is 64-bits on all Windows compilers
  1238.  
  1239.     WIN32_FILE_ATTRIBUTE_DATA fad;
  1240.  
  1241.     if (error(::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad)== 0
  1242.       ? BOOST_ERRNO : 0, p, ec, "mars_boost::filesystem::file_size"))
  1243.           return static_cast<mars_boost::uintmax_t>(-1);
  1244.  
  1245.     if (error((fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!= 0
  1246.       ? ERROR_NOT_SUPPORTED : 0, p, ec, "mars_boost::filesystem::file_size"))
  1247.       return static_cast<mars_boost::uintmax_t>(-1);
  1248.  
  1249.     return (static_cast<mars_boost::uintmax_t>(fad.nFileSizeHigh)
  1250.               << (sizeof(fad.nFileSizeLow)*8)) + fad.nFileSizeLow;
  1251. #   endif
  1252.   }
  1253.  
  1254.   BOOST_FILESYSTEM_DECL
  1255.   mars_boost::uintmax_t hard_link_count(const path& p, system::error_code* ec)
  1256.   {
  1257. #   ifdef BOOST_POSIX_API
  1258.  
  1259.     struct stat path_stat;
  1260.     return error(::stat(p.c_str(), &path_stat)!= 0 ? BOOST_ERRNO : 0,
  1261.                   p, ec, "mars_boost::filesystem::hard_link_count")
  1262.            ? 0
  1263.            : static_cast<mars_boost::uintmax_t>(path_stat.st_nlink);
  1264.  
  1265. #   else // Windows
  1266.  
  1267.     // Link count info is only available through GetFileInformationByHandle
  1268.     BY_HANDLE_FILE_INFORMATION info;
  1269.     handle_wrapper h(
  1270.       create_file_handle(p.c_str(), 0,
  1271.           FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
  1272.           OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
  1273.     return
  1274.       !error(h.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0,
  1275.               p, ec, "mars_boost::filesystem::hard_link_count")
  1276.       && !error(::GetFileInformationByHandle(h.handle, &info)== 0 ? BOOST_ERRNO : 0,
  1277.                  p, ec, "mars_boost::filesystem::hard_link_count")
  1278.            ? info.nNumberOfLinks
  1279.            : 0;
  1280. #   endif
  1281.   }
  1282.  
  1283.   BOOST_FILESYSTEM_DECL
  1284.   path initial_path(error_code* ec)
  1285.   {
  1286.       static path init_path;
  1287.       if (init_path.empty())
  1288.         init_path = current_path(ec);
  1289.       else if (ec != 0) ec->clear();
  1290.       return init_path;
  1291.   }
  1292.  
  1293.   BOOST_FILESYSTEM_DECL
  1294.   bool is_empty(const path& p, system::error_code* ec)
  1295.   {
  1296. #   ifdef BOOST_POSIX_API
  1297.  
  1298.     struct stat path_stat;
  1299.     if (error(::stat(p.c_str(), &path_stat)!= 0,
  1300.         p, ec, "mars_boost::filesystem::is_empty"))
  1301.       return false;        
  1302.     return S_ISDIR(path_stat.st_mode)
  1303.       ? is_empty_directory(p)
  1304.       : path_stat.st_size == 0;
  1305. #   else
  1306.  
  1307.     WIN32_FILE_ATTRIBUTE_DATA fad;
  1308.     if (error(::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad)== 0
  1309.       ? BOOST_ERRNO : 0, p, ec, "mars_boost::filesystem::is_empty"))
  1310.         return false;
  1311.  
  1312.     if (ec != 0) ec->clear();
  1313.     return
  1314.       (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1315.         ? is_empty_directory(p)
  1316.         : (!fad.nFileSizeHigh && !fad.nFileSizeLow);
  1317. #   endif
  1318.   }
  1319.  
  1320.   BOOST_FILESYSTEM_DECL
  1321.   std::time_t last_write_time(const path& p, system::error_code* ec)
  1322.   {
  1323. #   ifdef BOOST_POSIX_API
  1324.  
  1325.     struct stat path_stat;
  1326.     if (error(::stat(p.c_str(), &path_stat)!= 0 ? BOOST_ERRNO : 0,
  1327.       p, ec, "mars_boost::filesystem::last_write_time"))
  1328.         return std::time_t(-1);
  1329.     return path_stat.st_mtime;
  1330.  
  1331. #   else
  1332.  
  1333.     handle_wrapper hw(
  1334.       create_file_handle(p.c_str(), 0,
  1335.         FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
  1336.         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
  1337.  
  1338.     if (error(hw.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0,
  1339.       p, ec, "mars_boost::filesystem::last_write_time"))
  1340.         return std::time_t(-1);
  1341.  
  1342.     FILETIME lwt;
  1343.  
  1344.     if (error(::GetFileTime(hw.handle, 0, 0, &lwt)== 0 ? BOOST_ERRNO : 0,
  1345.       p, ec, "mars_boost::filesystem::last_write_time"))
  1346.         return std::time_t(-1);
  1347.  
  1348.     return to_time_t(lwt);
  1349. #   endif
  1350.   }
  1351.  
  1352.   BOOST_FILESYSTEM_DECL
  1353.   void last_write_time(const path& p, const std::time_t new_time,
  1354.                         system::error_code* ec)
  1355.   {
  1356. #   ifdef BOOST_POSIX_API
  1357.  
  1358.     struct stat path_stat;
  1359.     if (error(::stat(p.c_str(), &path_stat)!= 0,
  1360.       p, ec, "mars_boost::filesystem::last_write_time"))
  1361.         return;
  1362.     ::utimbuf buf;
  1363.     buf.actime = path_stat.st_atime; // utime()updates access time too:-(
  1364.     buf.modtime = new_time;
  1365.     error(::utime(p.c_str(), &buf)!= 0 ? BOOST_ERRNO : 0,
  1366.       p, ec, "mars_boost::filesystem::last_write_time");
  1367.  
  1368. #   else
  1369.  
  1370.     handle_wrapper hw(
  1371.       create_file_handle(p.c_str(), FILE_WRITE_ATTRIBUTES,
  1372.         FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
  1373.         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
  1374.  
  1375.     if (error(hw.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0,
  1376.       p, ec, "mars_boost::filesystem::last_write_time"))
  1377.         return;
  1378.  
  1379.     FILETIME lwt;
  1380.     to_FILETIME(new_time, lwt);
  1381.  
  1382.     error(::SetFileTime(hw.handle, 0, 0, &lwt)== 0 ? BOOST_ERRNO : 0,
  1383.       p, ec, "mars_boost::filesystem::last_write_time");
  1384. #   endif
  1385.   }
  1386.  
  1387. # ifdef BOOST_POSIX_API
  1388.     const perms active_bits(all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit);
  1389.     inline mode_t mode_cast(perms prms) { return prms & active_bits; }
  1390. # endif
  1391.  
  1392.   BOOST_FILESYSTEM_DECL
  1393.   void permissions(const path& p, perms prms, system::error_code* ec)
  1394.   {
  1395.     BOOST_ASSERT_MSG(!((prms & add_perms) && (prms & remove_perms)),
  1396.       "add_perms and remove_perms are mutually exclusive");
  1397.  
  1398.     if ((prms & add_perms) && (prms & remove_perms))  // precondition failed
  1399.       return;
  1400.  
  1401. # ifdef BOOST_POSIX_API
  1402.     error_code local_ec;
  1403.     file_status current_status((prms & symlink_perms)
  1404.                                ? fs::symlink_status(p, local_ec)
  1405.                                : fs::status(p, local_ec));
  1406.     if (local_ec)
  1407.     {
  1408.       if (ec == 0)
  1409.       BOOST_FILESYSTEM_THROW(filesystem_error(
  1410.           "mars_boost::filesystem::permissions", p, local_ec));
  1411.       else
  1412.         *ec = local_ec;
  1413.       return;
  1414.     }
  1415.  
  1416.     if (prms & add_perms)
  1417.       prms |= current_status.permissions();
  1418.     else if (prms & remove_perms)
  1419.       prms = current_status.permissions() & ~prms;
  1420.  
  1421.     // OS X <10.10, iOS <8.0 and some other platforms don't support fchmodat().
  1422.     // Solaris (SunPro and gcc) only support fchmodat() on Solaris 11 and higher,
  1423.     // and a runtime check is too much trouble.
  1424.     // Linux does not support permissions on symbolic links and has no plans to
  1425.     // support them in the future.  The chmod() code is thus more practical,
  1426.     // rather than always hitting ENOTSUP when sending in AT_SYMLINK_NO_FOLLOW.
  1427.     //  - See the 3rd paragraph of
  1428.     // "Symbolic link ownership, permissions, and timestamps" at:
  1429.     //   "http://man7.org/linux/man-pages/man7/symlink.7.html"
  1430.     //  - See the fchmodat() Linux man page:
  1431.     //   "http://man7.org/linux/man-pages/man2/fchmodat.2.html"
  1432. #   if defined(AT_FDCWD) && defined(AT_SYMLINK_NOFOLLOW) \
  1433.       && !(defined(__SUNPRO_CC) || defined(__sun) || defined(sun)) \
  1434.       && !(defined(linux) || defined(__linux) || defined(__linux__)) \
  1435.       && !(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
  1436.            && __MAC_OS_X_VERSION_MIN_REQUIRED < 101000) \
  1437.       && !(defined(__IPHONE_OS_VERSION_MIN_REQUIRED) \
  1438.            && __IPHONE_OS_VERSION_MIN_REQUIRED < 80000)
  1439.       if (::fchmodat(AT_FDCWD, p.c_str(), mode_cast(prms),
  1440.            !(prms & symlink_perms) ? 0 : AT_SYMLINK_NOFOLLOW))
  1441. #   else  // fallback if fchmodat() not supported
  1442.       if (::chmod(p.c_str(), mode_cast(prms)))
  1443. #   endif
  1444.     {
  1445.       if (ec == 0)
  1446.       BOOST_FILESYSTEM_THROW(filesystem_error(
  1447.           "mars_boost::filesystem::permissions", p,
  1448.           error_code(errno, system::generic_category())));
  1449.       else
  1450.         ec->assign(errno, system::generic_category());
  1451.     }
  1452.  
  1453. # else  // Windows
  1454.  
  1455.     // if not going to alter FILE_ATTRIBUTE_READONLY, just return
  1456.     if (!(!((prms & (add_perms | remove_perms)))
  1457.       || (prms & (owner_write|group_write|others_write))))
  1458.       return;
  1459.  
  1460.     DWORD attr = ::GetFileAttributesW(p.c_str());
  1461.  
  1462.     if (error(attr == 0 ? BOOST_ERRNO : 0, p, ec, "mars_boost::filesystem::permissions"))
  1463.       return;
  1464.  
  1465.     if (prms & add_perms)
  1466.       attr &= ~FILE_ATTRIBUTE_READONLY;
  1467.     else if (prms & remove_perms)
  1468.       attr |= FILE_ATTRIBUTE_READONLY;
  1469.     else if (prms & (owner_write|group_write|others_write))
  1470.       attr &= ~FILE_ATTRIBUTE_READONLY;
  1471.     else
  1472.       attr |= FILE_ATTRIBUTE_READONLY;
  1473.  
  1474.     error(::SetFileAttributesW(p.c_str(), attr) == 0 ? BOOST_ERRNO : 0,
  1475.       p, ec, "mars_boost::filesystem::permissions");
  1476. # endif
  1477.   }
  1478.  
  1479.   BOOST_FILESYSTEM_DECL
  1480.   path read_symlink(const path& p, system::error_code* ec)
  1481.   {
  1482.     path symlink_path;
  1483.  
  1484. #   ifdef BOOST_POSIX_API
  1485.  
  1486.     for (std::size_t path_max = 64;; path_max *= 2)// loop 'til buffer large enough
  1487.     {
  1488.       mars_boost::scoped_array<char> buf(new char[path_max]);
  1489.       ssize_t result;
  1490.       if ((result=::readlink(p.c_str(), buf.get(), path_max))== -1)
  1491.       {
  1492.         if (ec == 0)
  1493.           BOOST_FILESYSTEM_THROW(filesystem_error("mars_boost::filesystem::read_symlink",
  1494.             p, error_code(errno, system_category())));
  1495.         else ec->assign(errno, system_category());
  1496.         break;
  1497.       }
  1498.       else
  1499.       {
  1500.         if(result != static_cast<ssize_t>(path_max))
  1501.         {
  1502.           symlink_path.assign(buf.get(), buf.get() + result);
  1503.           if (ec != 0) ec->clear();
  1504.           break;
  1505.         }
  1506.       }
  1507.     }
  1508.  
  1509. #   elif _WIN32_WINNT < 0x0600  // SDK earlier than Vista and Server 2008
  1510.     error(BOOST_ERROR_NOT_SUPPORTED, p, ec,
  1511.           "mars_boost::filesystem::read_symlink");
  1512. #   else  // Vista and Server 2008 SDK, or later
  1513.  
  1514.     union info_t
  1515.     {
  1516.       char buf[REPARSE_DATA_BUFFER_HEADER_SIZE+MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
  1517.       REPARSE_DATA_BUFFER rdb;
  1518.     } info;
  1519.  
  1520.     handle_wrapper h(
  1521.       create_file_handle(p.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING,
  1522.         FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0));
  1523.  
  1524.     if (error(h.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0,
  1525.       p, ec, "mars_boost::filesystem::read_symlink"))
  1526.         return symlink_path;
  1527.  
  1528.     DWORD sz;
  1529.  
  1530.     if (!error(::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT,
  1531.           0, 0, info.buf, sizeof(info), &sz, 0) == 0 ? BOOST_ERRNO : 0, p, ec,
  1532.           "mars_boost::filesystem::read_symlink" ))
  1533.       symlink_path.assign(
  1534.         static_cast<wchar_t*>(info.rdb.SymbolicLinkReparseBuffer.PathBuffer)
  1535.         + info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(wchar_t),
  1536.         static_cast<wchar_t*>(info.rdb.SymbolicLinkReparseBuffer.PathBuffer)
  1537.         + info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(wchar_t)
  1538.         + info.rdb.SymbolicLinkReparseBuffer.PrintNameLength/sizeof(wchar_t));
  1539. #     endif
  1540.     return symlink_path;
  1541.   }
  1542.  
  1543.   BOOST_FILESYSTEM_DECL
  1544.   path relative(const path& p, const path& base, error_code* ec)
  1545.   {
  1546.     error_code tmp_ec;
  1547.     path wc_base(weakly_canonical(base, &tmp_ec));
  1548.     if (error(tmp_ec.value(), base, ec, "mars_boost::filesystem::relative"))
  1549.       return path();
  1550.     path wc_p(weakly_canonical(p, &tmp_ec));
  1551.     if (error(tmp_ec.value(), base, ec, "mars_boost::filesystem::relative"))
  1552.       return path();
  1553.     return wc_p.lexically_relative(wc_base);
  1554.   }
  1555.  
  1556.   BOOST_FILESYSTEM_DECL
  1557.   bool remove(const path& p, error_code* ec)
  1558.   {
  1559.     error_code tmp_ec;
  1560.     file_type type = query_file_type(p, &tmp_ec);
  1561.     if (error(type == status_error ? tmp_ec.value() : 0, p, ec,
  1562.         "mars_boost::filesystem::remove"))
  1563.       return false;
  1564.  
  1565.     // Since POSIX remove() is specified to work with either files or directories, in a
  1566.     // perfect world it could just be called. But some important real-world operating
  1567.     // systems (Windows, Mac OS X, for example) don't implement the POSIX spec. So
  1568.     // remove_file_or_directory() is always called to keep it simple.
  1569.     return remove_file_or_directory(p, type, ec);
  1570.   }
  1571.  
  1572.   BOOST_FILESYSTEM_DECL
  1573.   mars_boost::uintmax_t remove_all(const path& p, error_code* ec)
  1574.   {
  1575.     error_code tmp_ec;
  1576.     file_type type = query_file_type(p, &tmp_ec);
  1577.     if (error(type == status_error ? tmp_ec.value() : 0, p, ec,
  1578.       "mars_boost::filesystem::remove_all"))
  1579.       return 0;
  1580.  
  1581.     return (type != status_error && type != file_not_found) // exists
  1582.       ? remove_all_aux(p, type, ec)
  1583.       : 0;
  1584.   }
  1585.  
  1586.   BOOST_FILESYSTEM_DECL
  1587.   void rename(const path& old_p, const path& new_p, error_code* ec)
  1588.   {
  1589.     error(!BOOST_MOVE_FILE(old_p.c_str(), new_p.c_str()) ? BOOST_ERRNO : 0, old_p, new_p,
  1590.       ec, "mars_boost::filesystem::rename");
  1591.   }
  1592.  
  1593.   BOOST_FILESYSTEM_DECL
  1594.   void resize_file(const path& p, uintmax_t size, system::error_code* ec)
  1595.   {
  1596.     error(!BOOST_RESIZE_FILE(p.c_str(), size) ? BOOST_ERRNO : 0, p, ec,
  1597.       "mars_boost::filesystem::resize_file");
  1598.   }
  1599.  
  1600.   BOOST_FILESYSTEM_DECL
  1601.   space_info space(const path& p, error_code* ec)
  1602.   {
  1603. #   ifdef BOOST_POSIX_API
  1604.     struct BOOST_STATVFS vfs;
  1605.     space_info info;
  1606.     if (!error(::BOOST_STATVFS(p.c_str(), &vfs)!= 0,
  1607.       p, ec, "mars_boost::filesystem::space"))
  1608.     {
  1609.       info.capacity
  1610.         = static_cast<mars_boost::uintmax_t>(vfs.f_blocks)* BOOST_STATVFS_F_FRSIZE;
  1611.       info.free
  1612.         = static_cast<mars_boost::uintmax_t>(vfs.f_bfree)* BOOST_STATVFS_F_FRSIZE;
  1613.       info.available
  1614.         = static_cast<mars_boost::uintmax_t>(vfs.f_bavail)* BOOST_STATVFS_F_FRSIZE;
  1615.     }
  1616.  
  1617. #   else
  1618.     ULARGE_INTEGER avail, total, free;
  1619.     space_info info;
  1620.  
  1621.     if (!error(::GetDiskFreeSpaceExW(p.c_str(), &avail, &total, &free)== 0,
  1622.        p, ec, "mars_boost::filesystem::space"))
  1623.     {
  1624.       info.capacity
  1625.         = (static_cast<mars_boost::uintmax_t>(total.HighPart)<< 32)
  1626.           + total.LowPart;
  1627.       info.free
  1628.         = (static_cast<mars_boost::uintmax_t>(free.HighPart)<< 32)
  1629.           + free.LowPart;
  1630.       info.available
  1631.         = (static_cast<mars_boost::uintmax_t>(avail.HighPart)<< 32)
  1632.           + avail.LowPart;
  1633.     }
  1634.  
  1635. #   endif
  1636.  
  1637.     else
  1638.     {
  1639.       info.capacity = info.free = info.available = 0;
  1640.     }
  1641.     return info;
  1642.   }
  1643.  
  1644.   BOOST_FILESYSTEM_DECL
  1645.   file_status status(const path& p, error_code* ec)
  1646.   {
  1647. #   ifdef BOOST_POSIX_API
  1648.  
  1649.     struct stat path_stat;
  1650.     if (::stat(p.c_str(), &path_stat)!= 0)
  1651.     {
  1652.       if (ec != 0)                            // always report errno, even though some
  1653.         ec->assign(errno, system_category());   // errno values are not status_errors
  1654.  
  1655.       if (not_found_error(errno))
  1656.       {
  1657.         return fs::file_status(fs::file_not_found, fs::no_perms);
  1658.       }
  1659.       if (ec == 0)
  1660.         BOOST_FILESYSTEM_THROW(filesystem_error("mars_boost::filesystem::status",
  1661.           p, error_code(errno, system_category())));
  1662.       return fs::file_status(fs::status_error);
  1663.     }
  1664.     if (ec != 0) ec->clear();;
  1665.     if (S_ISDIR(path_stat.st_mode))
  1666.       return fs::file_status(fs::directory_file,
  1667.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1668.     if (S_ISREG(path_stat.st_mode))
  1669.       return fs::file_status(fs::regular_file,
  1670.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1671.     if (S_ISBLK(path_stat.st_mode))
  1672.       return fs::file_status(fs::block_file,
  1673.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1674.     if (S_ISCHR(path_stat.st_mode))
  1675.       return fs::file_status(fs::character_file,
  1676.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1677.     if (S_ISFIFO(path_stat.st_mode))
  1678.       return fs::file_status(fs::fifo_file,
  1679.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1680.     if (S_ISSOCK(path_stat.st_mode))
  1681.       return fs::file_status(fs::socket_file,
  1682.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1683.     return fs::file_status(fs::type_unknown);
  1684.  
  1685. #   else  // Windows
  1686.  
  1687.     DWORD attr(::GetFileAttributesW(p.c_str()));
  1688.     if (attr == 0xFFFFFFFF)
  1689.     {
  1690.       return process_status_failure(p, ec);
  1691.     }
  1692.  
  1693.     //  reparse point handling;
  1694.     //    since GetFileAttributesW does not resolve symlinks, try to open a file
  1695.     //    handle to discover if the file exists
  1696.     if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
  1697.     {
  1698.       handle_wrapper h(
  1699.         create_file_handle(
  1700.             p.c_str(),
  1701.             0,  // dwDesiredAccess; attributes only
  1702.             FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  1703.             0,  // lpSecurityAttributes
  1704.             OPEN_EXISTING,
  1705.             FILE_FLAG_BACKUP_SEMANTICS,
  1706.             0)); // hTemplateFile
  1707.       if (h.handle == INVALID_HANDLE_VALUE)
  1708.       {
  1709.         return process_status_failure(p, ec);
  1710.       }
  1711.  
  1712.       if (!is_reparse_point_a_symlink(p))
  1713.         return file_status(reparse_file, make_permissions(p, attr));
  1714.     }
  1715.  
  1716.     if (ec != 0) ec->clear();
  1717.     return (attr & FILE_ATTRIBUTE_DIRECTORY)
  1718.       ? file_status(directory_file, make_permissions(p, attr))
  1719.       : file_status(regular_file, make_permissions(p, attr));
  1720.  
  1721. #   endif
  1722.   }
  1723.  
  1724.   BOOST_FILESYSTEM_DECL
  1725.   file_status symlink_status(const path& p, error_code* ec)
  1726.   {
  1727. #   ifdef BOOST_POSIX_API
  1728.  
  1729.     struct stat path_stat;
  1730.     if (::lstat(p.c_str(), &path_stat)!= 0)
  1731.     {
  1732.       if (ec != 0)                            // always report errno, even though some
  1733.         ec->assign(errno, system_category());   // errno values are not status_errors
  1734.  
  1735.       if (errno == ENOENT || errno == ENOTDIR) // these are not errors
  1736.       {
  1737.         return fs::file_status(fs::file_not_found, fs::no_perms);
  1738.       }
  1739.       if (ec == 0)
  1740.         BOOST_FILESYSTEM_THROW(filesystem_error("mars_boost::filesystem::status",
  1741.           p, error_code(errno, system_category())));
  1742.       return fs::file_status(fs::status_error);
  1743.     }
  1744.     if (ec != 0) ec->clear();
  1745.     if (S_ISREG(path_stat.st_mode))
  1746.       return fs::file_status(fs::regular_file,
  1747.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1748.     if (S_ISDIR(path_stat.st_mode))
  1749.       return fs::file_status(fs::directory_file,
  1750.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1751.     if (S_ISLNK(path_stat.st_mode))
  1752.       return fs::file_status(fs::symlink_file,
  1753.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1754.     if (S_ISBLK(path_stat.st_mode))
  1755.       return fs::file_status(fs::block_file,
  1756.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1757.     if (S_ISCHR(path_stat.st_mode))
  1758.       return fs::file_status(fs::character_file,
  1759.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1760.     if (S_ISFIFO(path_stat.st_mode))
  1761.       return fs::file_status(fs::fifo_file,
  1762.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1763.     if (S_ISSOCK(path_stat.st_mode))
  1764.       return fs::file_status(fs::socket_file,
  1765.         static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
  1766.     return fs::file_status(fs::type_unknown);
  1767.  
  1768. #   else  // Windows
  1769.  
  1770.     DWORD attr(::GetFileAttributesW(p.c_str()));
  1771.     if (attr == 0xFFFFFFFF)
  1772.     {
  1773.       return process_status_failure(p, ec);
  1774.     }
  1775.  
  1776.     if (ec != 0) ec->clear();
  1777.  
  1778.     if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
  1779.       return is_reparse_point_a_symlink(p)
  1780.              ? file_status(symlink_file, make_permissions(p, attr))
  1781.              : file_status(reparse_file, make_permissions(p, attr));
  1782.  
  1783.     return (attr & FILE_ATTRIBUTE_DIRECTORY)
  1784.       ? file_status(directory_file, make_permissions(p, attr))
  1785.       : file_status(regular_file, make_permissions(p, attr));
  1786.  
  1787. #   endif
  1788.   }
  1789.  
  1790.    // contributed by Jeff Flinn
  1791.   BOOST_FILESYSTEM_DECL
  1792.   path temp_directory_path(system::error_code* ec)
  1793.   {
  1794. #   ifdef BOOST_POSIX_API
  1795.       const char* val = 0;
  1796.      
  1797.       (val = std::getenv("TMPDIR" )) ||
  1798.       (val = std::getenv("TMP"    )) ||
  1799.       (val = std::getenv("TEMP"   )) ||
  1800.       (val = std::getenv("TEMPDIR"));
  1801.      
  1802. #     ifdef __ANDROID__
  1803.         const char* default_tmp = "/data/local/tmp";
  1804. #     else
  1805.         const char* default_tmp = "/tmp";
  1806. #     endif
  1807.       path p((val!=0) ? val : default_tmp);
  1808.        
  1809.       if (p.empty() || (ec&&!is_directory(p, *ec))||(!ec&&!is_directory(p)))
  1810.       {
  1811.         error(ENOTDIR, p, ec, "mars_boost::filesystem::temp_directory_path");
  1812.         return p;
  1813.       }
  1814.        
  1815.       return p;
  1816.      
  1817. #   else  // Windows
  1818.  
  1819.       const wchar_t* tmp_env = L"TMP";
  1820.       const wchar_t* temp_env = L"TEMP";
  1821.       const wchar_t* localappdata_env = L"LOCALAPPDATA";
  1822.       const wchar_t* userprofile_env = L"USERPROFILE";
  1823.       const wchar_t* env_list[]
  1824.         = {tmp_env, temp_env, localappdata_env, userprofile_env, 0};
  1825.  
  1826.       path p;
  1827.       for (int i = 0; env_list[i]; ++i)
  1828.       {
  1829.         std::wstring env = wgetenv(env_list[i]);
  1830.         if (!env.empty())
  1831.         {
  1832.           p = env;
  1833.           if (i >= 2)
  1834.             p /= L"Temp";
  1835.           error_code lcl_ec;
  1836.           if (exists(p, lcl_ec) && !lcl_ec && is_directory(p, lcl_ec) && !lcl_ec)
  1837.             break;
  1838.           p.clear();
  1839.         }
  1840.       }
  1841.  
  1842.       if (p.empty())
  1843.       {
  1844.         // use vector since in C++03 a string is not required to be contiguous
  1845.         std::vector<wchar_t> buf(::GetWindowsDirectoryW(NULL, 0));
  1846.  
  1847.         if (buf.empty()
  1848.           || ::GetWindowsDirectoryW(&buf[0], static_cast<UINT>(buf.size())) == 0)
  1849.         {
  1850.           error(::GetLastError(), ec, "mars_boost::filesystem::temp_directory_path");
  1851.           return path();
  1852.         }
  1853.         p = &*buf.begin();  // do not depend on buf.size(); see ticket #10388
  1854.         p /= L"Temp";
  1855.       }
  1856.       return p;
  1857.  
  1858. #   endif
  1859.   }
  1860.  
  1861.   BOOST_FILESYSTEM_DECL
  1862.   path system_complete(const path& p, system::error_code* ec)
  1863.   {
  1864. #   ifdef BOOST_POSIX_API
  1865.     return (p.empty() || p.is_absolute())
  1866.       ? p : current_path()/ p;
  1867.  
  1868. #   else
  1869.     if (p.empty())
  1870.     {
  1871.       if (ec != 0) ec->clear();
  1872.       return p;
  1873.     }
  1874.     wchar_t buf[buf_size];
  1875.     wchar_t* pfn;
  1876.     std::size_t len = get_full_path_name(p, buf_size, buf, &pfn);
  1877.  
  1878.     if (error(len == 0 ? BOOST_ERRNO : 0, p, ec, "mars_boost::filesystem::system_complete"))
  1879.       return path();
  1880.  
  1881.     if (len < buf_size)// len does not include null termination character
  1882.       return path(&buf[0]);
  1883.  
  1884.     mars_boost::scoped_array<wchar_t> big_buf(new wchar_t[len]);
  1885.  
  1886.     return error(get_full_path_name(p, len , big_buf.get(), &pfn)== 0 ? BOOST_ERRNO : 0,
  1887.       p, ec, "mars_boost::filesystem::system_complete")
  1888.       ? path()
  1889.       : path(big_buf.get());
  1890. #   endif
  1891.   }
  1892.  
  1893.   BOOST_FILESYSTEM_DECL
  1894.   path weakly_canonical(const path& p, system::error_code* ec)
  1895.   {
  1896.     path head(p);
  1897.     path tail;
  1898.     system::error_code tmp_ec;
  1899.     path::iterator itr = p.end();
  1900.  
  1901.     for (; !head.empty(); --itr)
  1902.     {
  1903.       file_status head_status = status(head, tmp_ec);
  1904.       if (error(head_status.type() == fs::status_error,
  1905.         head, ec, "mars_boost::filesystem::weakly_canonical"))
  1906.         return path();
  1907.       if (head_status.type() != fs::file_not_found)
  1908.         break;
  1909.       head.remove_filename();
  1910.     }
  1911.  
  1912.     bool tail_has_dots = false;
  1913.     for (; itr != p.end(); ++itr)
  1914.     {
  1915.       tail /= *itr;
  1916.       // for a later optimization, track if any dot or dot-dot elements are present
  1917.       if (itr->native().size() <= 2
  1918.         && itr->native()[0] == dot
  1919.         && (itr->native().size() == 1 || itr->native()[1] == dot))
  1920.         tail_has_dots = true;
  1921.     }
  1922.    
  1923.     if (head.empty())
  1924.       return p.lexically_normal();
  1925.     head = canonical(head, tmp_ec);
  1926.     if (error(tmp_ec.value(), head, ec, "mars_boost::filesystem::weakly_canonical"))
  1927.       return path();
  1928.     return tail.empty()
  1929.       ? head
  1930.       : (tail_has_dots  // optimization: only normalize if tail had dot or dot-dot element
  1931.           ? (head/tail).lexically_normal()  
  1932.           : head/tail);
  1933.   }
  1934. }  // namespace detail
  1935.  
  1936. //--------------------------------------------------------------------------------------//
  1937. //                                                                                      //
  1938. //                                 directory_entry                                      //
  1939. //                                                                                      //
  1940. //--------------------------------------------------------------------------------------//
  1941.  
  1942.   file_status
  1943.   directory_entry::m_get_status(system::error_code* ec) const
  1944.   {
  1945.     if (!status_known(m_status))
  1946.     {
  1947.       // optimization: if the symlink status is known, and it isn't a symlink,
  1948.       // then status and symlink_status are identical so just copy the
  1949.       // symlink status to the regular status.
  1950.       if (status_known(m_symlink_status)
  1951.         && !is_symlink(m_symlink_status))
  1952.       {
  1953.         m_status = m_symlink_status;
  1954.         if (ec != 0) ec->clear();
  1955.       }
  1956.       else m_status = detail::status(m_path, ec);
  1957.     }
  1958.     else if (ec != 0) ec->clear();
  1959.     return m_status;
  1960.   }
  1961.  
  1962.   file_status
  1963.   directory_entry::m_get_symlink_status(system::error_code* ec) const
  1964.   {
  1965.     if (!status_known(m_symlink_status))
  1966.       m_symlink_status = detail::symlink_status(m_path, ec);
  1967.     else if (ec != 0) ec->clear();
  1968.     return m_symlink_status;
  1969.   }
  1970.  
  1971. //  dispatch directory_entry supplied here rather than in
  1972. //  <boost/filesystem/path_traits.hpp>, thus avoiding header circularity.
  1973. //  test cases are in operations_unit_test.cpp
  1974.  
  1975. namespace path_traits
  1976. {
  1977.   void dispatch(const directory_entry & de,
  1978. #                ifdef BOOST_WINDOWS_API
  1979.     std::wstring& to,
  1980. #                else  
  1981.     std::string& to,
  1982. #                endif
  1983.     const codecvt_type &)
  1984.   {
  1985.     to = de.path().native();
  1986.   }
  1987.  
  1988.   void dispatch(const directory_entry & de,
  1989. #                ifdef BOOST_WINDOWS_API
  1990.     std::wstring& to
  1991. #                else  
  1992.     std::string& to
  1993. #                endif
  1994.     )
  1995.   {
  1996.     to = de.path().native();
  1997.   }
  1998. }  // namespace path_traits
  1999. } // namespace filesystem
  2000. } // namespace mars_boost
  2001.  
  2002. //--------------------------------------------------------------------------------------//
  2003. //                                                                                      //
  2004. //                               directory_iterator                                     //
  2005. //                                                                                      //
  2006. //--------------------------------------------------------------------------------------//
  2007.  
  2008. namespace
  2009. {
  2010. # ifdef BOOST_POSIX_API
  2011.  
  2012.   error_code path_max(std::size_t & result)
  2013.   // this code is based on Stevens and Rago, Advanced Programming in the
  2014.   // UNIX envirnment, 2nd Ed., ISBN 0-201-43307-9, page 49
  2015.   {
  2016. #   ifdef PATH_MAX
  2017.     static std::size_t max = PATH_MAX;
  2018. #   else
  2019.     static std::size_t max = 0;
  2020. #   endif
  2021.     if (max == 0)
  2022.     {
  2023.       errno = 0;
  2024.       long tmp = ::pathconf("/", _PC_NAME_MAX);
  2025.       if (tmp < 0)
  2026.       {
  2027.         if (errno == 0)// indeterminate
  2028.           max = 4096; // guess
  2029.         else return error_code(errno, system_category());
  2030.       }
  2031.       else max = static_cast<std::size_t>(tmp + 1); // relative root
  2032.     }
  2033.     result = max;
  2034.     return ok;
  2035.   }
  2036.  
  2037. #if defined(__PGI) && defined(__USE_FILE_OFFSET64)
  2038. #define dirent dirent64
  2039. #endif
  2040.  
  2041.   error_code dir_itr_first(void *& handle, void *& buffer,
  2042.     const char* dir, string& target,
  2043.     fs::file_status &, fs::file_status &)
  2044.   {
  2045.     if ((handle = ::opendir(dir))== 0)
  2046.       return error_code(errno, system_category());
  2047.     target = string(".");  // string was static but caused trouble
  2048.                              // when iteration called from dtor, after
  2049.                              // static had already been destroyed
  2050.     std::size_t path_size (0);  // initialization quiets gcc warning (ticket #3509)
  2051.     error_code ec = path_max(path_size);
  2052.     if (ec)return ec;
  2053.     dirent de;
  2054.     buffer = std::malloc((sizeof(dirent) - sizeof(de.d_name))
  2055.       +  path_size + 1); // + 1 for "/0"
  2056.     return ok;
  2057.   }  
  2058.  
  2059.   // warning: the only dirent member updated is d_name
  2060.   inline int readdir_r_simulator(DIR * dirp, struct dirent * entry,
  2061.     struct dirent ** result)// *result set to 0 on end of directory
  2062.   {
  2063.     errno = 0;
  2064.  
  2065. #   if !defined(__CYGWIN__)\
  2066.     && defined(_POSIX_THREAD_SAFE_FUNCTIONS)\
  2067.     && defined(_SC_THREAD_SAFE_FUNCTIONS)\
  2068.     && (_POSIX_THREAD_SAFE_FUNCTIONS+0 >= 0)\
  2069.     && (!defined(__hpux) || defined(_REENTRANT)) \
  2070.     && (!defined(_AIX) || defined(__THREAD_SAFE))
  2071.     if (::sysconf(_SC_THREAD_SAFE_FUNCTIONS)>= 0)
  2072.       { return ::readdir_r(dirp, entry, result); }
  2073. #   endif
  2074.  
  2075.     struct dirent * p;
  2076.     *result = 0;
  2077.     if ((p = ::readdir(dirp))== 0)
  2078.       return errno;
  2079.     std::strcpy(entry->d_name, p->d_name);
  2080.     *result = entry;
  2081.     return 0;
  2082.   }
  2083.  
  2084.   error_code dir_itr_increment(void *& handle, void *& buffer,
  2085.     string& target, fs::file_status & sf, fs::file_status & symlink_sf)
  2086.   {
  2087.     BOOST_ASSERT(buffer != 0);
  2088.     dirent * entry(static_cast<dirent *>(buffer));
  2089.     dirent * result;
  2090.     int return_code;
  2091.     if ((return_code = readdir_r_simulator(static_cast<DIR*>(handle), entry, &result))!= 0)
  2092.       return error_code(errno, system_category());
  2093.     if (result == 0)
  2094.       return fs::detail::dir_itr_close(handle, buffer);
  2095.     target = entry->d_name;
  2096. #   ifdef BOOST_FILESYSTEM_STATUS_CACHE
  2097.     if (entry->d_type == DT_UNKNOWN) // filesystem does not supply d_type value
  2098.     {
  2099.       sf = symlink_sf = fs::file_status(fs::status_error);
  2100.     }
  2101.     else  // filesystem supplies d_type value
  2102.     {
  2103.       if (entry->d_type == DT_DIR)
  2104.         sf = symlink_sf = fs::file_status(fs::directory_file);
  2105.       else if (entry->d_type == DT_REG)
  2106.         sf = symlink_sf = fs::file_status(fs::regular_file);
  2107.       else if (entry->d_type == DT_LNK)
  2108.       {
  2109.         sf = fs::file_status(fs::status_error);
  2110.         symlink_sf = fs::file_status(fs::symlink_file);
  2111.       }
  2112.       else sf = symlink_sf = fs::file_status(fs::status_error);
  2113.     }
  2114. #   else
  2115.     sf = symlink_sf = fs::file_status(fs::status_error);
  2116. #    endif
  2117.     return ok;
  2118.   }
  2119.  
  2120. # else // BOOST_WINDOWS_API
  2121.  
  2122.   error_code dir_itr_first(void *& handle, const fs::path& dir,
  2123.     wstring& target, fs::file_status & sf, fs::file_status & symlink_sf)
  2124.   // Note: an empty root directory has no "." or ".." entries, so this
  2125.   // causes a ERROR_FILE_NOT_FOUND error which we do not considered an
  2126.   // error. It is treated as eof instead.
  2127.   {
  2128.     // use a form of search Sebastian Martel reports will work with Win98
  2129.     wstring dirpath(dir.wstring());
  2130.     dirpath += (dirpath.empty()
  2131.       || (dirpath[dirpath.size()-1] != L'\\'
  2132.         && dirpath[dirpath.size()-1] != L'/'
  2133.         && dirpath[dirpath.size()-1] != L':'))? L"\\*" : L"*";
  2134.  
  2135.     WIN32_FIND_DATAW data;
  2136.     if ((handle = ::FindFirstFileW(dirpath.c_str(), &data))
  2137.       == INVALID_HANDLE_VALUE)
  2138.     {
  2139.       handle = 0;  // signal eof
  2140.       return error_code( (::GetLastError() == ERROR_FILE_NOT_FOUND
  2141.                        // Windows Mobile returns ERROR_NO_MORE_FILES; see ticket #3551                                          
  2142.                        || ::GetLastError() == ERROR_NO_MORE_FILES)
  2143.         ? 0 : ::GetLastError(), system_category() );
  2144.     }
  2145.     target = data.cFileName;
  2146.     if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
  2147.     // reparse points are complex, so don't try to handle them here; instead just mark
  2148.     // them as status_error which causes directory_entry caching to call status()
  2149.     // and symlink_status() which do handle reparse points fully
  2150.     {
  2151.       sf.type(fs::status_error);
  2152.       symlink_sf.type(fs::status_error);
  2153.     }
  2154.     else
  2155.     {
  2156.       if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  2157.       {
  2158.         sf.type(fs::directory_file);
  2159.         symlink_sf.type(fs::directory_file);
  2160.       }
  2161.       else
  2162.       {
  2163.         sf.type(fs::regular_file);
  2164.         symlink_sf.type(fs::regular_file);
  2165.       }
  2166.       sf.permissions(make_permissions(data.cFileName, data.dwFileAttributes));
  2167.       symlink_sf.permissions(sf.permissions());
  2168.     }
  2169.     return error_code();
  2170.   }
  2171.  
  2172.   error_code  dir_itr_increment(void *& handle, wstring& target,
  2173.     fs::file_status & sf, fs::file_status & symlink_sf)
  2174.   {
  2175.     WIN32_FIND_DATAW data;
  2176.     if (::FindNextFileW(handle, &data)== 0)// fails
  2177.     {
  2178.       int error = ::GetLastError();
  2179.       fs::detail::dir_itr_close(handle);
  2180.       return error_code(error == ERROR_NO_MORE_FILES ? 0 : error, system_category());
  2181.     }
  2182.     target = data.cFileName;
  2183.     if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
  2184.     // reparse points are complex, so don't try to handle them here; instead just mark
  2185.     // them as status_error which causes directory_entry caching to call status()
  2186.     // and symlink_status() which do handle reparse points fully
  2187.     {
  2188.       sf.type(fs::status_error);
  2189.       symlink_sf.type(fs::status_error);
  2190.     }
  2191.     else
  2192.     {
  2193.       if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  2194.       {
  2195.         sf.type(fs::directory_file);
  2196.         symlink_sf.type(fs::directory_file);
  2197.       }
  2198.       else
  2199.       {
  2200.         sf.type(fs::regular_file);
  2201.         symlink_sf.type(fs::regular_file);
  2202.       }
  2203.       sf.permissions(make_permissions(data.cFileName, data.dwFileAttributes));
  2204.       symlink_sf.permissions(sf.permissions());
  2205.     }
  2206.     return error_code();
  2207.   }
  2208. #endif
  2209.  
  2210.   const error_code not_found_error_code (
  2211. #     ifdef BOOST_WINDOWS_API
  2212.         ERROR_PATH_NOT_FOUND
  2213. #     else
  2214.         ENOENT
  2215. #     endif
  2216.         , system_category());
  2217.  
  2218. }  // unnamed namespace
  2219.  
  2220. namespace mars_boost {} namespace boost = mars_boost; namespace mars_boost
  2221. {
  2222. namespace filesystem
  2223. {
  2224.  
  2225. namespace detail
  2226. {
  2227.   //  dir_itr_close is called both from the ~dir_itr_imp()destructor
  2228.   //  and dir_itr_increment()
  2229.   BOOST_FILESYSTEM_DECL
  2230.   system::error_code dir_itr_close( // never throws
  2231.     void *& handle
  2232. #   if defined(BOOST_POSIX_API)
  2233.     , void *& buffer
  2234. #   endif
  2235.    )
  2236.   {
  2237. #   ifdef BOOST_POSIX_API
  2238.     std::free(buffer);
  2239.     buffer = 0;
  2240.     if (handle == 0)return ok;
  2241.     DIR * h(static_cast<DIR*>(handle));
  2242.     handle = 0;
  2243.     return error_code(::closedir(h)== 0 ? 0 : errno, system_category());
  2244.  
  2245. #   else
  2246.     if (handle != 0)
  2247.     {
  2248.       ::FindClose(handle);
  2249.       handle = 0;
  2250.     }
  2251.     return ok;
  2252.  
  2253. #   endif
  2254.   }
  2255.  
  2256.   void directory_iterator_construct(directory_iterator& it,
  2257.     const path& p, system::error_code* ec)    
  2258.   {
  2259.     if (error(p.empty() ? not_found_error_code.value() : 0, p, ec,
  2260.               "mars_boost::filesystem::directory_iterator::construct"))
  2261.       return;
  2262.  
  2263.     path::string_type filename;
  2264.     file_status file_stat, symlink_file_stat;
  2265.     error_code result = dir_itr_first(it.m_imp->handle,
  2266. #     if defined(BOOST_POSIX_API)
  2267.       it.m_imp->buffer,
  2268. #     endif
  2269.       p.c_str(), filename, file_stat, symlink_file_stat);
  2270.  
  2271.     if (result)
  2272.     {
  2273.       it.m_imp.reset();
  2274.       error(result.value(), p,
  2275.         ec, "mars_boost::filesystem::directory_iterator::construct");
  2276.       return;
  2277.     }
  2278.    
  2279.     if (it.m_imp->handle == 0)
  2280.       it.m_imp.reset(); // eof, so make end iterator
  2281.     else // not eof
  2282.     {
  2283.       it.m_imp->dir_entry.assign(p / filename, file_stat, symlink_file_stat);
  2284.       if (filename[0] == dot // dot or dot-dot
  2285.         && (filename.size()== 1
  2286.           || (filename[1] == dot
  2287.             && filename.size()== 2)))
  2288.         {  it.increment(*ec); }
  2289.     }
  2290.   }
  2291.  
  2292.   void directory_iterator_increment(directory_iterator& it,
  2293.     system::error_code* ec)
  2294.   {
  2295.     BOOST_ASSERT_MSG(it.m_imp.get(), "attempt to increment end iterator");
  2296.     BOOST_ASSERT_MSG(it.m_imp->handle != 0, "internal program error");
  2297.    
  2298.     path::string_type filename;
  2299.     file_status file_stat, symlink_file_stat;
  2300.     system::error_code temp_ec;
  2301.  
  2302.     for (;;)
  2303.     {
  2304.       temp_ec = dir_itr_increment(it.m_imp->handle,
  2305. #       if defined(BOOST_POSIX_API)
  2306.         it.m_imp->buffer,
  2307. #       endif
  2308.         filename, file_stat, symlink_file_stat);
  2309.  
  2310.       if (temp_ec)  // happens if filesystem is corrupt, such as on a damaged optical disc
  2311.       {
  2312.         path error_path(it.m_imp->dir_entry.path().parent_path());  // fix ticket #5900
  2313.         it.m_imp.reset();
  2314.         if (ec == 0)
  2315.           BOOST_FILESYSTEM_THROW(
  2316.             filesystem_error("mars_boost::filesystem::directory_iterator::operator++",
  2317.               error_path,
  2318.               error_code(BOOST_ERRNO, system_category())));
  2319.         else
  2320.           ec->assign(BOOST_ERRNO, system_category());
  2321.         return;
  2322.       }
  2323.       else if (ec != 0) ec->clear();
  2324.  
  2325.       if (it.m_imp->handle == 0)  // eof, make end
  2326.       {
  2327.         it.m_imp.reset();
  2328.         return;
  2329.       }
  2330.  
  2331.       if (!(filename[0] == dot // !(dot or dot-dot)
  2332.         && (filename.size()== 1
  2333.           || (filename[1] == dot
  2334.             && filename.size()== 2))))
  2335.       {
  2336.         it.m_imp->dir_entry.replace_filename(
  2337.           filename, file_stat, symlink_file_stat);
  2338.         return;
  2339.       }
  2340.     }
  2341.   }
  2342. }  // namespace detail
  2343. } // namespace filesystem
  2344. } // namespace mars_boost
  2345.  
downloadoperations.cpp Source code - Download mars Source code
Related Source Codes/Software:
Hero - Elegant transition library for iOS & tvOS 2017-06-09
deep-photo-styletransfer - Code and data for paper "Deep Photo Style Transfer... 2017-06-09
mastodon - A GNU Social-compatible microblogging server ... 2017-06-09
plyr - A simple HTML5, YouTube and Vimeo player ... 2017-06-08
prepack - Prepack is a partial evaluator for JavaScript. Pre... 2017-06-08
Public-APIs - 2017-06-09
lottie-ios - An iOS library to natively render After Effects ve... 2017-06-09
Awesome-Hacking - A collection of various awesome lists for hackers,... 2017-06-09
algorithms - Minimal examples of data structures and algorithms... 2017-06-10
lectures - Oxford Deep NLP 2017 course 2017-06-10
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top