Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r66021 - in branches/release: boost boost/filesystem boost/filesystem/v2 boost/filesystem/v3 libs/filesystem libs/filesystem/v2/test libs/filesystem/v3/doc libs/filesystem/v3/src libs/filesystem/v3/test libs/filesystem/v3/test/msvc libs/filesystem/v3/test/msvc10 libs/filesystem/v3/test/msvc10/windows_attributes
From: bdawes_at_[hidden]
Date: 2010-10-16 09:09:42


Author: bemandawes
Date: 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
New Revision: 66021
URL: http://svn.boost.org/trac/boost/changeset/66021

Log:
Merge from trunk, with several important fixes
Added:
   branches/release/libs/filesystem/v3/test/msvc10/windows_attributes/
      - copied from r66019, /trunk/libs/filesystem/v3/test/msvc10/windows_attributes/
   branches/release/libs/filesystem/v3/test/msvc10/windows_attributes/windows_attributes.vcxproj
      - copied unchanged from r66019, /trunk/libs/filesystem/v3/test/msvc10/windows_attributes/windows_attributes.vcxproj
   branches/release/libs/filesystem/v3/test/windows_attributes.cpp
      - copied unchanged from r66019, /trunk/libs/filesystem/v3/test/windows_attributes.cpp
Properties modified:
   branches/release/boost/filesystem/ (props changed)
   branches/release/boost/filesystem.hpp (props changed)
   branches/release/libs/filesystem/ (props changed)
Text files modified:
   branches/release/boost/filesystem/v2/operations.hpp | 2
   branches/release/boost/filesystem/v2/path.hpp | 5
   branches/release/boost/filesystem/v3/operations.hpp | 19 +
   branches/release/boost/filesystem/v3/path.hpp | 14
   branches/release/boost/filesystem/v3/path_traits.hpp | 29 +
   branches/release/libs/filesystem/v2/test/path_test.cpp | 2
   branches/release/libs/filesystem/v3/doc/reference.html | 29 +
   branches/release/libs/filesystem/v3/src/operations.cpp | 204 ++++++++++------
   branches/release/libs/filesystem/v3/src/path.cpp | 2
   branches/release/libs/filesystem/v3/src/windows_file_codecvt.cpp | 1
   branches/release/libs/filesystem/v3/test/msvc/filesystem-v3.sln | 4
   branches/release/libs/filesystem/v3/test/msvc10/filesystem-v3.sln | 4
   branches/release/libs/filesystem/v3/test/operations_test.cpp | 475 ++++++++++++++++++++++++++-------------
   branches/release/libs/filesystem/v3/test/operations_unit_test.cpp | 6
   branches/release/libs/filesystem/v3/test/path_test.cpp | 5
   branches/release/libs/filesystem/v3/test/path_unit_test.cpp | 24 ++
   branches/release/libs/filesystem/v3/test/test_codecvt.hpp | 3
   17 files changed, 570 insertions(+), 258 deletions(-)

Modified: branches/release/boost/filesystem/v2/operations.hpp
==============================================================================
--- branches/release/boost/filesystem/v2/operations.hpp (original)
+++ branches/release/boost/filesystem/v2/operations.hpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -1188,7 +1188,9 @@
     using filesystem2::copy_file;
     using filesystem2::copy_option;
     using filesystem2::create_directory;
+# if !defined(BOOST_WINDOWS_API) || defined(BOOST_FS_HARD_LINK)
     using filesystem2::create_hard_link;
+# endif
     using filesystem2::create_symlink;
     using filesystem2::current_path;
     using filesystem2::directory_entry;

Modified: branches/release/boost/filesystem/v2/path.hpp
==============================================================================
--- branches/release/boost/filesystem/v2/path.hpp (original)
+++ branches/release/boost/filesystem/v2/path.hpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -1532,6 +1532,11 @@
   {
     using filesystem2::basic_path;
     using filesystem2::path_traits;
+
+ using filesystem2::slash;
+ using filesystem2::dot;
+ using filesystem2::colon;
+
     using filesystem2::path;
 # ifndef BOOST_FILESYSTEM2_NARROW_ONLY
     using filesystem2::wpath_traits;

Modified: branches/release/boost/filesystem/v3/operations.hpp
==============================================================================
--- branches/release/boost/filesystem/v3/operations.hpp (original)
+++ branches/release/boost/filesystem/v3/operations.hpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -68,14 +68,17 @@
     file_not_found,
     regular_file,
     directory_file,
- // the following will never be reported by some operating or file systems
+ // the following may not apply to some operating systems or file systems
     symlink_file,
     block_file,
     character_file,
     fifo_file,
     socket_file,
- type_unknown // file does exist, but isn't one of the above types or
- // we don't have strong enough permission to find its type
+ reparse_file, // Windows: FILE_ATTRIBUTE_REPARSE_POINT that is not a symlink
+ type_unknown, // file does exist, but isn't one of the above types or
+ // we don't have strong enough permission to find its type
+
+ _detail_directory_symlink // internal use only; never exposed to users
   };
 
   class BOOST_FILESYSTEM_DECL file_status
@@ -145,7 +148,7 @@
                     BOOST_SCOPED_ENUM(copy_option) option, // See ticket #2925
                     system::error_code* ec=0);
     BOOST_FILESYSTEM_DECL
- void copy_symlink(const path& from, const path& to, system::error_code* ec=0);
+ void copy_symlink(const path& existing_symlink, const path& new_symlink, system::error_code* ec=0);
     BOOST_FILESYSTEM_DECL
     bool create_directories(const path& p, system::error_code* ec=0);
     BOOST_FILESYSTEM_DECL
@@ -304,11 +307,11 @@
   void copy_file(const path& from, const path& to, system::error_code& ec)
                                        {detail::copy_file(from, to, copy_option::fail_if_exists, &ec);}
   inline
- void copy_symlink(const path& from, const path& to) {detail::copy_symlink(from, to);}
+ void copy_symlink(const path& existing_symlink, const path& new_symlink) {detail::copy_symlink(existing_symlink, new_symlink);}
 
   inline
- void copy_symlink(const path& from, const path& to, system::error_code& ec)
- {detail::copy_symlink(from, to, &ec);}
+ void copy_symlink(const path& existing_symlink, const path& new_symlink, system::error_code& ec)
+ {detail::copy_symlink(existing_symlink, new_symlink, &ec);}
   inline
   bool create_directories(const path& p) {return detail::create_directories(p);}
 
@@ -938,6 +941,7 @@
     using filesystem3::absolute;
     using filesystem3::block_file;
     using filesystem3::character_file;
+// using filesystem3::copy;
     using filesystem3::copy_file;
     using filesystem3::copy_option;
     using filesystem3::copy_symlink;
@@ -945,6 +949,7 @@
     using filesystem3::create_directory;
     using filesystem3::create_hard_link;
     using filesystem3::create_symlink;
+ using filesystem3::create_directory_symlink;
     using filesystem3::current_path;
     using filesystem3::directory_entry;
     using filesystem3::directory_file;

Modified: branches/release/boost/filesystem/v3/path.hpp
==============================================================================
--- branches/release/boost/filesystem/v3/path.hpp (original)
+++ branches/release/boost/filesystem/v3/path.hpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -22,7 +22,7 @@
 # endif
 
 #include <boost/filesystem/v3/config.hpp>
-#include <boost/filesystem/v3/path_traits.hpp>
+#include <boost/filesystem/v3/path_traits.hpp> // includes <cwchar>
 #include <boost/system/error_code.hpp>
 #include <boost/system/system_error.hpp>
 #include <boost/iterator/iterator_facade.hpp>
@@ -127,7 +127,9 @@
     path(const path& p) : m_pathname(p.m_pathname) {}
  
     template <class Source>
- path(Source const& source)
+ path(Source const& source,
+ typename boost::enable_if<path_traits::is_pathable<
+ typename boost::decay<Source>::type> >::type* =0)
     {
       path_traits::dispatch(source, m_pathname, codecvt());
     }
@@ -170,7 +172,9 @@
     }
 
     template <class Source>
- path& operator=(Source const& source)
+ typename boost::enable_if<path_traits::is_pathable<
+ typename boost::decay<Source>::type>, path&>::type
+ operator=(Source const& source)
     {
       m_pathname.clear();
       path_traits::dispatch(source, m_pathname, codecvt());
@@ -212,7 +216,9 @@
     path& operator/=(const path& p);
 
     template <class Source>
- path& operator/=(Source const& source)
+ typename boost::enable_if<path_traits::is_pathable<
+ typename boost::decay<Source>::type>, path&>::type
+ operator/=(Source const& source)
     {
       return append(source, codecvt());
     }

Modified: branches/release/boost/filesystem/v3/path_traits.hpp
==============================================================================
--- branches/release/boost/filesystem/v3/path_traits.hpp (original)
+++ branches/release/boost/filesystem/v3/path_traits.hpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -19,9 +19,12 @@
 #include <boost/filesystem/v3/config.hpp>
 #include <boost/utility/enable_if.hpp>
 #include <boost/type_traits/is_array.hpp>
+#include <boost/type_traits/decay.hpp>
 #include <boost/system/error_code.hpp>
+#include <cwchar> // for mbstate_t
 #include <string>
 #include <vector>
+#include <list>
 #include <iterator>
 #include <locale>
 #include <boost/assert.hpp>
@@ -48,6 +51,23 @@
  
   typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_type;
 
+ // is_pathable type trait; allows disabling over-agressive class path member templates
+
+ template <class T>
+ struct is_pathable { static const bool value = false; };
+
+ template<> struct is_pathable<char*> { static const bool value = true; };
+ template<> struct is_pathable<const char*> { static const bool value = true; };
+ template<> struct is_pathable<wchar_t*> { static const bool value = true; };
+ template<> struct is_pathable<const wchar_t*> { static const bool value = true; };
+ template<> struct is_pathable<std::string> { static const bool value = true; };
+ template<> struct is_pathable<std::wstring> { static const bool value = true; };
+ template<> struct is_pathable<std::vector<char> > { static const bool value = true; };
+ template<> struct is_pathable<std::vector<wchar_t> > { static const bool value = true; };
+ template<> struct is_pathable<std::list<char> > { static const bool value = true; };
+ template<> struct is_pathable<std::list<wchar_t> > { static const bool value = true; };
+ template<> struct is_pathable<directory_entry> { static const bool value = true; };
+
   // Pathable empty
 
   template <class Container> inline
@@ -195,13 +215,8 @@
     convert(c_str, to, cvt);
   }
   
- // C-style array
- template <typename T, size_t N, class U> inline
- void dispatch(T (&array)[N], U& to, const codecvt_type& cvt) // T, N, U deduced
- {
-// std::cout << "dispatch() array, N=" << N << "\n";
- convert(array, array + N - 1, to, cvt);
- }
+ // Note: there is no dispatch on C-style arrays because the array may
+ // contain a string smaller than the array size.
 
   BOOST_FILESYSTEM_DECL
   void dispatch(const directory_entry & de,

Modified: branches/release/libs/filesystem/v2/test/path_test.cpp
==============================================================================
--- branches/release/libs/filesystem/v2/test/path_test.cpp (original)
+++ branches/release/libs/filesystem/v2/test/path_test.cpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -1329,6 +1329,7 @@
 // extension() tests
 
   BOOST_TEST( path("a/b").extension() == "" );
+ BOOST_TEST( path("a.b/c").extension() == "" );
   BOOST_TEST( path("a/b.txt").extension() == ".txt" );
   BOOST_TEST( path("a/b.").extension() == "." );
   BOOST_TEST( path("a.b.c").extension() == ".c" );
@@ -1359,6 +1360,7 @@
   BOOST_TEST( path("a.b.txt" ).replace_extension("tex").string() == "a.b.tex" );
   // see the rationale in html docs for explanation why this works
   BOOST_TEST( path("").replace_extension(".png").string() == ".png" );
+ BOOST_TEST_EQ(path("a.txt/b").replace_extension(".c"), "a.txt/b.c"); // ticket 4702
 
   // inserter and extractor tests
 # if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 // bypass VC++ 7.0 and earlier

Modified: branches/release/libs/filesystem/v3/doc/reference.html
==============================================================================
--- branches/release/libs/filesystem/v3/doc/reference.html (original)
+++ branches/release/libs/filesystem/v3/doc/reference.html 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -337,23 +337,35 @@
 
 </span> path absolute(const path&amp; p, const path&amp; base=current_path());
 
+ void copy(const path&amp; from, const path&amp; to);
+ void copy(const path&amp; from, const path&amp; to, system::error_code&amp; ec);
+
+ void copy_directory(const path&amp; from, const path&amp; to);
+ void copy_directory(const path&amp; from, const path&amp; to, system::error_code&amp; ec);
+
       void copy_file(const path&amp; from, const path&amp; to);
       void copy_file(const path&amp; from, const path&amp; to, system::error_code&amp; ec);
       void copy_file(const path&amp; from, const path&amp; to, BOOST_SCOPED_ENUM(copy_option) option);
       void copy_file(const path&amp; from, const path&amp; to, BOOST_SCOPED_ENUM(copy_option) option,
                              system::error_code&amp; ec);
 
+ void copy_symlink(const path&amp; existing_symlink, const path&amp; new_symlink);
+ void copy_symlink(const path&amp; existing_symlink, const path&amp; new_symlink, system::error_code&amp; ec);
+
       bool create_directories(const path&amp; p);
       bool create_directories(const path&amp; p, system::error_code&amp; ec);
 
       bool create_directory(const path&amp; p);
       bool create_directory(const path&amp; p, system::error_code&amp; ec);
 
- void create_hard_link(const path&amp; to, const path&amp; from);
- void create_hard_link(const path&amp; to, const path&amp; from, system::error_code&amp; ec);
+<span style="background-color: #FFFFFF"> void create_directory_symlink(const path&amp; to, const path&amp; </span>new_symlink<span style="background-color: #FFFFFF">);
+ void create_directory_symlink(const path&amp; to, const path&amp; </span>new_symlink, system::error_code&amp; ec<span style="background-color: #FFFFFF">);
+</span>
+ void create_hard_link(const path&amp; to, const path&amp; new_hard_link);
+ void create_hard_link(const path&amp; to, const path&amp; new_hard_link, system::error_code&amp; ec);
 
-<span style="background-color: #FFFFFF"> void create_symlink(const path&amp; to, const path&amp; from);
- void create_symlink(const path&amp; to, const path&amp; from</span>, system::error_code&amp; ec<span style="background-color: #FFFFFF">);
+<span style="background-color: #FFFFFF"> void create_symlink(const path&amp; to, const path&amp; </span>new_symlink<span style="background-color: #FFFFFF">);
+ void create_symlink(const path&amp; to, const path&amp; </span>new_symlink, system::error_code&amp; ec<span style="background-color: #FFFFFF">);
 
 </span> path current_path();
       path current_path(system::error_code&amp; ec);
@@ -368,7 +380,9 @@
       bool equivalent(const path&amp; p1, const path&amp; p2, system::error_code&amp; ec);
 
       <span style="background-color: #FFFFFF; ">uintmax_t</span> file_size(const path&amp; p);
- <span style="background-color: #FFFFFF; ">uintmax_t</span> file_size(const path&amp; p, system::error_code&amp; ec);
+ <span style="background-color: #FFFFFF; ">uintmax_t</span> file_size(const path&amp; p, system::error_code&amp; ec);</pre>
+<pre> uintmax_t hard_link_count(const path&amp; p);
+ uintmax_t hard_link_count(const path&amp; p, system::error_code&amp; ec);
 
       bool is_directory(file_status s);
       bool is_directory(const path&amp; p);
@@ -406,6 +420,9 @@
       void rename(const path&amp; from, const path&amp; to);
       void rename(const path&amp; from, const path&amp; to, system::error_code&amp; ec);
 
+ void resize_file(const path&amp; p, uintmax_t size);
+ void resize_file(const path&amp; p, uintmax_t size, system::error_code&amp; ec);
+
 <span style="background-color: #FFFFFF"> space_info space(const path&amp; p);
       <a href="#space_info">space_info</a> <a href="#space">space</a>(const path&amp; p</span>, system::error_code&amp; ec<span style="background-color: #FFFFFF">);
 </span><span style="background-color: #FFFF00">
@@ -3052,7 +3069,7 @@
 <p>Distributed under the Boost Software License, Version 1.0. See
 <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
 <p>Revised
-<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->02 July 2010<!--webbot bot="Timestamp" endspan i-checksum="18762" --></p>
+<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->05 October 2010<!--webbot bot="Timestamp" endspan i-checksum="32123" --></p>
 
 </body>
 

Modified: branches/release/libs/filesystem/v3/src/operations.cpp
==============================================================================
--- branches/release/libs/filesystem/v3/src/operations.cpp (original)
+++ branches/release/libs/filesystem/v3/src/operations.cpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -150,8 +150,16 @@
 #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 )
 #endif
 
+# ifndef FSCTL_GET_REPARSE_POINT
+# define FSCTL_GET_REPARSE_POINT 0x900a8
 # endif
 
+# ifndef IO_REPARSE_TAG_SYMLINK
+# define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
+# endif
+
+# endif // BOOST_WINDOWS_API
+
 // BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in
 // dir_itr_increment. The config tests are placed here because some of the
 // macros being tested come from dirent.h.
@@ -234,6 +242,8 @@
   const wchar_t dot = L'.';
 # endif
 
+ fs::file_type query_file_type(const path& p, error_code* ec);
+
   boost::filesystem3::directory_iterator end_dir_itr;
 
   const std::size_t buf_size(128);
@@ -339,16 +349,20 @@
     { return BOOST_DELETE_FILE(p.c_str()); }
   
   // called by remove and remove_all_aux
- bool remove_file_or_directory(const path& p, fs::file_status sym_stat, error_code* ec)
+ bool remove_file_or_directory(const path& p, fs::file_type type, error_code* ec)
     // return true if file removed, false if not removed
   {
- if (sym_stat.type()== fs::file_not_found)
+ if (type == fs::file_not_found)
     {
       if (ec != 0) ec->clear();
       return false;
     }
 
- if (fs::is_directory(sym_stat))
+ if (type == fs::directory_file
+# ifdef BOOST_WINDOWS_API
+ || type == fs::_detail_directory_symlink
+# endif
+ )
     {
       if (error(!remove_directory(p), p, ec, "boost::filesystem::remove"))
         return false;
@@ -361,24 +375,23 @@
     return true;
   }
 
- boost::uintmax_t remove_all_aux(const path& p, fs::file_status sym_stat,
+ boost::uintmax_t remove_all_aux(const path& p, fs::file_type type,
     error_code* ec)
   {
     boost::uintmax_t count = 1;
 
- if (!fs::is_symlink(sym_stat)// don't recurse symbolic links
- && fs::is_directory(sym_stat))
+ if (type == fs::directory_file) // but not a directory symlink
     {
       for (fs::directory_iterator itr(p);
             itr != end_dir_itr; ++itr)
       {
- fs::file_status tmp_sym_stat = fs::symlink_status(itr->path(), *ec);
- if (ec != 0 && ec)
+ fs::file_type tmp_type = query_file_type(itr->path(), ec);
+ if (ec != 0 && *ec)
           return count;
- count += remove_all_aux(itr->path(), tmp_sym_stat, ec);
+ count += remove_all_aux(itr->path(), tmp_type, ec);
       }
     }
- remove_file_or_directory(p, sym_stat, ec);
+ remove_file_or_directory(p, type, ec);
     return count;
   }
 
@@ -449,6 +462,11 @@
     return sz_read >= 0;
   }
 
+ inline fs::file_type query_file_type(const path& p, error_code* ec)
+ {
+ return fs::detail::symlink_status(p, ec).type();
+ }
+
 # else
 
 //--------------------------------------------------------------------------------------//
@@ -512,7 +530,7 @@
     }
   };
 
- HANDLE create_file_handle(path p, DWORD dwDesiredAccess,
+ HANDLE create_file_handle(const path& p, DWORD dwDesiredAccess,
     DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
     DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
     HANDLE hTemplateFile)
@@ -522,6 +540,26 @@
       hTemplateFile);
   }
 
+ bool is_reparse_point_a_symlink(const path& p)
+ {
+ handle_wrapper h(create_file_handle(p, FILE_READ_EA,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL));
+ if (h.handle == INVALID_HANDLE_VALUE)
+ return false;
+
+ boost::scoped_array<char> buf(new char [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
+
+ // Query the reparse data
+ DWORD dwRetLen;
+ BOOL result = ::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buf.get(),
+ MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dwRetLen, NULL);
+ if (!result) return false;
+
+ return reinterpret_cast<const REPARSE_DATA_BUFFER*>(buf.get())
+ ->ReparseTag == IO_REPARSE_TAG_SYMLINK;
+ }
+
   inline std::size_t get_full_path_name(
     const path& src, std::size_t len, wchar_t* buf, wchar_t** p)
   {
@@ -529,6 +567,52 @@
       ::GetFullPathNameW(src.c_str(), static_cast<DWORD>(len), buf, p));
   }
 
+ fs::file_status process_status_failure(const path& p, error_code* ec)
+ {
+ int errval(::GetLastError());
+ if (ec != 0) // always report errval, even though some
+ ec->assign(errval, system_category()); // errval values are not status_errors
+
+ if (not_found_error(errval))
+ {
+ return fs::file_status(fs::file_not_found);
+ }
+ else if ((errval == ERROR_SHARING_VIOLATION))
+ {
+ return fs::file_status(fs::type_unknown);
+ }
+ if (ec == 0)
+ BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
+ p, error_code(errval, system_category())));
+ return fs::file_status(fs::status_error);
+ }
+
+ // differs from symlink_status() in that directory symlinks are reported as
+ // _detail_directory_symlink, as required on Windows by remove() and its helpers.
+ fs::file_type query_file_type(const path& p, error_code* ec)
+ {
+ DWORD attr(::GetFileAttributesW(p.c_str()));
+ if (attr == 0xFFFFFFFF)
+ {
+ return process_status_failure(p, ec).type();
+ }
+
+ if (ec != 0) ec->clear();
+
+ if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
+ {
+ if (is_reparse_point_a_symlink(p))
+ return (attr & FILE_ATTRIBUTE_DIRECTORY)
+ ? fs::_detail_directory_symlink
+ : fs::symlink_file;
+ return fs::reparse_file;
+ }
+
+ return (attr & FILE_ATTRIBUTE_DIRECTORY)
+ ? fs::directory_file
+ : fs::regular_file;
+ }
+
   BOOL resize_file_api(const wchar_t* p, boost::uintmax_t size)
   {
     HANDLE handle = CreateFileW(p, GENERIC_WRITE, 0, 0, OPEN_EXISTING,
@@ -563,6 +647,7 @@
   PtrCreateSymbolicLinkW create_symbolic_link_api = PtrCreateSymbolicLinkW(
     ::GetProcAddress(
       ::GetModuleHandle(TEXT("kernel32.dll")), "CreateSymbolicLinkW"));
+
 #endif
 
 //#ifdef BOOST_WINDOWS_API
@@ -659,7 +744,7 @@
   void copy(const path& from, const path& to, system::error_code* ec)
   {
     file_status s(symlink_status(from, *ec));
- if (ec != 0 && ec)return;
+ if (ec != 0 && *ec) return;
 
     if(is_symlink(s))
     {
@@ -703,32 +788,20 @@
   }
 
   BOOST_FILESYSTEM_DECL
- void copy_symlink(const path& from, const path& to, system::error_code* ec)
+ void copy_symlink(const path& existing_symlink, const path& new_symlink,
+ system::error_code* ec)
   {
-# ifdef BOOST_POSIX_API
- path p(read_symlink(from, ec));
- if (ec != 0 && ec) return;
- create_symlink(p, to, ec);
-
-# elif _WIN32_WINNT < 0x0600 // SDK earlier than Vista and Server 2008
- error(true, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()), to, from, ec,
+# if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
+ error(true, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()),
+ new_symlink, existing_symlink, ec,
       "boost::filesystem::copy_symlink");
 
-# else // modern Windows
-
- // see if actually supported by Windows runtime dll
- if (error(!create_symbolic_link_api,
- error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()),
- to, from, ec,
- "boost::filesystem3::copy_symlink"))
- return;
-
- // preconditions met, so attempt the copy
- error(!::CopyFileExW(from.c_str(), to.c_str(), 0, 0, 0,
- COPY_FILE_COPY_SYMLINK | COPY_FILE_FAIL_IF_EXISTS), to, from, ec,
- "boost::filesystem3::copy_symlink");
-# endif
+# else // modern Windows or BOOST_POSIX_API
+ path p(read_symlink(existing_symlink, ec));
+ if (ec != 0 && *ec) return;
+ create_symlink(p, new_symlink, ec);
 
+# endif
   }
 
   BOOST_FILESYSTEM_DECL
@@ -842,12 +915,12 @@
         if (error(!create_symbolic_link_api,
             error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()),
             to, from, ec,
- "boost::filesystem::create_directory_symlink"))
+ "boost::filesystem::create_symlink"))
           return;
 # endif
 
     error(!BOOST_CREATE_SYMBOLIC_LINK(from.c_str(), to.c_str(), 0),
- to, from, ec, "boost::filesystem::create_directory_symlink");
+ to, from, ec, "boost::filesystem::create_symlink");
 # endif
   }
 
@@ -1203,7 +1276,7 @@
     } info;
 
     handle_wrapper h(
- create_file_handle(p.c_str(),GENERIC_READ, 0, 0, OPEN_EXISTING,
+ create_file_handle(p.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING,
         FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0));
 
     if (error(h.handle == INVALID_HANDLE_VALUE, p, ec, "boost::filesystem::read_symlink"))
@@ -1228,25 +1301,29 @@
   bool remove(const path& p, error_code* ec)
   {
     error_code tmp_ec;
- file_status sym_status = symlink_status(p, tmp_ec);
- if (error(sym_status.type() == status_error, tmp_ec, p, ec,
+ file_type type = query_file_type(p, &tmp_ec);
+ if (error(type == status_error, tmp_ec, p, ec,
         "boost::filesystem::remove"))
       return false;
 
- return remove_file_or_directory(p, sym_status, ec);
+ // Since POSIX remove() is specified to work with either files or directories, in a
+ // perfect world it could just be called. But some important real-world operating
+ // systems (Windows, Mac OS X, for example) don't implement the POSIX spec. So
+ // remove_file_or_directory() is always called to kep it simple.
+ return remove_file_or_directory(p, type, ec);
   }
 
   BOOST_FILESYSTEM_DECL
   boost::uintmax_t remove_all(const path& p, error_code* ec)
   {
     error_code tmp_ec;
- file_status sym_status = symlink_status(p, tmp_ec);
- if (error(sym_status.type() == status_error, tmp_ec, p, ec,
+ file_type type = query_file_type(p, &tmp_ec);
+ if (error(type == status_error, tmp_ec, p, ec,
       "boost::filesystem::remove_all"))
       return 0;
 
- return exists(sym_status) // exists() throws nothing
- ? remove_all_aux(p, sym_status, ec)
+ return (type != status_error && type != file_not_found) // exists
+ ? remove_all_aux(p, type, ec)
       : 0;
   }
 
@@ -1307,29 +1384,6 @@
     return info;
   }
 
-# ifndef BOOST_POSIX_API
-
- file_status process_status_failure(const path& p, error_code* ec)
- {
- int errval(::GetLastError());
- if (ec != 0) // always report errval, even though some
- ec->assign(errval, system_category()); // errval values are not status_errors
-
- if (not_found_error(errval))
- {
- return file_status(file_not_found);
- }
- else if ((errval == ERROR_SHARING_VIOLATION))
- {
- return file_status(type_unknown);
- }
- if (ec == 0)
- BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
- p, error_code(errval, system_category())));
- return file_status(status_error);
- }
-# endif
-
   BOOST_FILESYSTEM_DECL
   file_status status(const path& p, error_code* ec)
   {
@@ -1370,11 +1424,11 @@
     DWORD attr(::GetFileAttributesW(p.c_str()));
     if (attr == 0xFFFFFFFF)
     {
- return detail::process_status_failure(p, ec);
+ return process_status_failure(p, ec);
     }
 
- // symlink handling
- if (attr & FILE_ATTRIBUTE_REPARSE_POINT)// aka symlink
+ // reparse point handling
+ if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
     {
       handle_wrapper h(
         create_file_handle(
@@ -1387,7 +1441,7 @@
             0)); // hTemplateFile
       if (h.handle == INVALID_HANDLE_VALUE)
       {
- return detail::process_status_failure(p, ec);
+ return process_status_failure(p, ec);
       }
     }
 
@@ -1441,13 +1495,15 @@
     DWORD attr(::GetFileAttributesW(p.c_str()));
     if (attr == 0xFFFFFFFF)
     {
- return detail::process_status_failure(p, ec);
+ return process_status_failure(p, ec);
     }
 
     if (ec != 0) ec->clear();
 
- if (attr & FILE_ATTRIBUTE_REPARSE_POINT)// aka symlink
- return file_status(symlink_file);
+ if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
+ return is_reparse_point_a_symlink(p)
+ ? file_status(symlink_file)
+ : file_status(reparse_file);
 
     return (attr & FILE_ATTRIBUTE_DIRECTORY)
       ? file_status(directory_file)

Modified: branches/release/libs/filesystem/v3/src/path.cpp
==============================================================================
--- branches/release/libs/filesystem/v3/src/path.cpp (original)
+++ branches/release/libs/filesystem/v3/src/path.cpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -236,7 +236,7 @@
   {
     // erase existing extension if any
     size_type pos(m_pathname.rfind(dot));
- if (pos != string_type::npos)
+ if (pos != string_type::npos && pos >= filename_pos(m_pathname, m_pathname.size()))
       m_pathname.erase(pos);
 
     // append source extension if any

Modified: branches/release/libs/filesystem/v3/src/windows_file_codecvt.cpp
==============================================================================
--- branches/release/libs/filesystem/v3/src/windows_file_codecvt.cpp (original)
+++ branches/release/libs/filesystem/v3/src/windows_file_codecvt.cpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -25,6 +25,7 @@
 #endif
 
 #include <boost/filesystem/v3/config.hpp>
+#include <cwchar> // for mbstate_t
 
 #ifdef BOOST_WINDOWS_API
 

Modified: branches/release/libs/filesystem/v3/test/msvc/filesystem-v3.sln
==============================================================================
--- branches/release/libs/filesystem/v3/test/msvc/filesystem-v3.sln (original)
+++ branches/release/libs/filesystem/v3/test/msvc/filesystem-v3.sln 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -92,6 +92,8 @@
                 {FFD738F7-96F0-445C-81EA-551665EF53D1} = {FFD738F7-96F0-445C-81EA-551665EF53D1}
         EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "enable_if_test", "enable_if_test\enable_if_test.vcproj", "{03FC7556-1052-45FF-A162-90D595713EAB}"
+EndProject
 Global
         GlobalSection(SolutionConfigurationPlatforms) = preSolution
                 Debug|Win32 = Debug|Win32
@@ -162,6 +164,8 @@
                 {F9F236A2-8B57-415A-8397-7145144400F5}.Debug|Win32.Build.0 = Debug|Win32
                 {F9F236A2-8B57-415A-8397-7145144400F5}.Release|Win32.ActiveCfg = Release|Win32
                 {F9F236A2-8B57-415A-8397-7145144400F5}.Release|Win32.Build.0 = Release|Win32
+ {03FC7556-1052-45FF-A162-90D595713EAB}.Debug|Win32.ActiveCfg = Debug|Win32
+ {03FC7556-1052-45FF-A162-90D595713EAB}.Release|Win32.ActiveCfg = Release|Win32
         EndGlobalSection
         GlobalSection(SolutionProperties) = preSolution
                 HideSolutionNode = FALSE

Modified: branches/release/libs/filesystem/v3/test/msvc10/filesystem-v3.sln
==============================================================================
--- branches/release/libs/filesystem/v3/test/msvc10/filesystem-v3.sln (original)
+++ branches/release/libs/filesystem/v3/test/msvc10/filesystem-v3.sln 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -27,6 +27,8 @@
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tut4", "tut4\tut4.vcxproj", "{256EA89A-E073-4CE8-B675-BE2FBC6B2691}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "windows_attributes", "windows_attributes\windows_attributes.vcxproj", "{FC5C770F-3017-4021-8DAF-C5DCA3FDF005}"
+EndProject
 Global
         GlobalSection(SolutionConfigurationPlatforms) = preSolution
                 Debug|Win32 = Debug|Win32
@@ -85,6 +87,8 @@
                 {256EA89A-E073-4CE8-B675-BE2FBC6B2691}.Debug|Win32.Build.0 = Debug|Win32
                 {256EA89A-E073-4CE8-B675-BE2FBC6B2691}.Release|Win32.ActiveCfg = Release|Win32
                 {256EA89A-E073-4CE8-B675-BE2FBC6B2691}.Release|Win32.Build.0 = Release|Win32
+ {FC5C770F-3017-4021-8DAF-C5DCA3FDF005}.Debug|Win32.ActiveCfg = Debug|Win32
+ {FC5C770F-3017-4021-8DAF-C5DCA3FDF005}.Release|Win32.ActiveCfg = Release|Win32
         EndGlobalSection
         GlobalSection(SolutionProperties) = preSolution
                 HideSolutionNode = FALSE

Modified: branches/release/libs/filesystem/v3/test/operations_test.cpp
==============================================================================
--- branches/release/libs/filesystem/v3/test/operations_test.cpp (original)
+++ branches/release/libs/filesystem/v3/test/operations_test.cpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -29,7 +29,6 @@
 #include <boost/cerrno.hpp>
 namespace fs = boost::filesystem;
 
-#include <boost/config.hpp>
 #include <boost/detail/lightweight_test.hpp>
 
 using boost::system::error_code;
@@ -39,9 +38,11 @@
 #include <fstream>
 #include <iostream>
 #include <string>
+#include <vector>
+#include <algorithm>
 #include <cstring> // for strncmp, etc.
 #include <ctime>
-#include <cstdlib> // for system()
+#include <cstdlib> // for system(), getenv(), etc.
 
 #ifdef BOOST_WINDOWS_API
 # include <windows.h>
@@ -69,6 +70,10 @@
   fs::path dir;
   fs::path d1;
   fs::path d2;
+ fs::path f0;
+ fs::path f1;
+ fs::path d1f1;
+
   bool create_symlink_ok(true);
   fs::path ng(" no-way, Jose");
 
@@ -301,7 +306,58 @@
 
     std::cout << " exception_tests complete" << std::endl;
   }
-
+
+ // create a directory tree that can be used by subsequent tests ---------------------//
+ //
+ // dir
+ // d1
+ // d1f1 // an empty file
+ // f0 // an empty file
+ // f1 // a file containing "file-f1"
+
+ void create_tree()
+ {
+
+ // create directory d1
+ BOOST_TEST(!fs::create_directory(dir));
+ BOOST_TEST(!fs::is_symlink(dir));
+ BOOST_TEST(!fs::is_symlink("nosuchfileordirectory"));
+ d1 = dir / "d1";
+ BOOST_TEST(fs::create_directory(d1));
+ BOOST_TEST(fs::exists(d1));
+ BOOST_TEST(fs::is_directory(d1));
+ BOOST_TEST(fs::is_empty(d1));
+
+ // create an empty file named "d1f1"
+ d1f1 = d1 / "d1f1";
+ create_file(d1f1, "");
+ BOOST_TEST(fs::exists(d1f1));
+ BOOST_TEST(!fs::is_directory(d1f1));
+ BOOST_TEST(fs::is_regular_file(d1f1));
+ BOOST_TEST(fs::is_empty(d1f1));
+ BOOST_TEST(fs::file_size(d1f1) == 0);
+ BOOST_TEST(fs::hard_link_count(d1f1) == 1);
+
+ // create an empty file named "f0"
+ f0 = dir / "f0";
+ create_file(f0, "");
+ BOOST_TEST(fs::exists(f0));
+ BOOST_TEST(!fs::is_directory(f0));
+ BOOST_TEST(fs::is_regular_file(f0));
+ BOOST_TEST(fs::is_empty(f0));
+ BOOST_TEST(fs::file_size(f0) == 0);
+ BOOST_TEST(fs::hard_link_count(f0) == 1);
+
+ // create a file named "f1"
+ f1 = dir / "f1";
+ create_file(f1, "file-f1");
+ BOOST_TEST(fs::exists(f1));
+ BOOST_TEST(!fs::is_directory(f1));
+ BOOST_TEST(fs::is_regular_file(f1));
+ BOOST_TEST(fs::file_size(f1) == 7);
+ verify_file(f1, "file-f1");
+ }
+
   // directory_iterator_tests --------------------------------------------------------//
 
   void directory_iterator_tests()
@@ -343,10 +399,14 @@
       // probe query function overloads
       fs::directory_iterator dir_itr(dir);
   // BOOST_TEST(fs::is_directory(*dir_itr));
- BOOST_TEST(fs::is_directory(dir_itr->status()));
+ BOOST_TEST(fs::is_directory(dir_itr->status())
+ || fs::is_regular_file(dir_itr->status()));
   // BOOST_TEST(fs::is_directory(fs::symlink_status(*dir_itr)));
- BOOST_TEST(fs::is_directory(dir_itr->symlink_status()));
- BOOST_TEST(dir_itr->path().filename() == "d1");
+ BOOST_TEST(fs::is_directory(dir_itr->symlink_status())
+ || fs::is_regular_file(dir_itr->symlink_status()));
+ BOOST_TEST(dir_itr->path().filename() == "d1"
+ || dir_itr->path().filename() == "d2" || dir_itr->path().filename() == "f0"
+ || dir_itr->path().filename() == "f1");
     }
   
     // create a second directory named d2
@@ -358,56 +418,76 @@
     // test the basic operation of directory_iterators, and test that
     // stepping one iterator doesn't affect a different iterator.
     {
- fs::directory_iterator dir_itr(dir);
- BOOST_TEST(fs::exists(dir_itr->status()));
- BOOST_TEST(fs::is_directory(dir_itr->status()));
- BOOST_TEST(!fs::is_regular_file(dir_itr->status()));
- BOOST_TEST(!fs::is_other(dir_itr->status()));
- BOOST_TEST(!fs::is_symlink(dir_itr->status()));
+ typedef std::vector<fs::directory_entry> vec_type;
+ vec_type vec;
 
- fs::directory_iterator dir_itr2(dir);
- BOOST_TEST(dir_itr->path().filename() == "d1"
- || dir_itr->path().filename() == "d2");
- BOOST_TEST(dir_itr2->path().filename() == "d1" || dir_itr2->path().filename() == "d2");
- if (dir_itr->path().filename() == "d1")
- {
- BOOST_TEST((++dir_itr)->path().filename() == "d2");
- BOOST_TEST(dir_itr2->path().filename() == "d1");
- BOOST_TEST((++dir_itr2)->path().filename() == "d2");
- }
- else
- {
- BOOST_TEST(dir_itr->path().filename() == "d2");
- BOOST_TEST((++dir_itr)->path().filename() == "d1");
- BOOST_TEST((dir_itr2)->path().filename() == "d2");
- BOOST_TEST((++dir_itr2)->path().filename() == "d1");
- }
- BOOST_TEST(++dir_itr == fs::directory_iterator());
- BOOST_TEST(dir_itr2 != fs::directory_iterator());
+ fs::directory_iterator it1(dir);
+ BOOST_TEST(it1 != fs::directory_iterator());
+ BOOST_TEST(fs::exists(it1->status()));
+ vec.push_back(*it1);
+ BOOST_TEST(*it1 == vec[0]);
+
+ fs::directory_iterator it2(dir);
+ BOOST_TEST(it2 != fs::directory_iterator());
+ BOOST_TEST(*it1 == *it2);
+
+ ++it1;
+ BOOST_TEST(it1 != fs::directory_iterator());
+ BOOST_TEST(fs::exists(it1->status()));
+ BOOST_TEST(it1 != it2);
+ BOOST_TEST(*it1 != vec[0]);
+ BOOST_TEST(*it2 == vec[0]);
+ vec.push_back(*it1);
+
+ ++it1;
+ BOOST_TEST(it1 != fs::directory_iterator());
+ BOOST_TEST(fs::exists(it1->status()));
+ BOOST_TEST(it1 != it2);
+ BOOST_TEST(*it2 == vec[0]);
+ vec.push_back(*it1);
+
+ ++it1;
+ BOOST_TEST(it1 != fs::directory_iterator());
+ BOOST_TEST(fs::exists(it1->status()));
+ BOOST_TEST(it1 != it2);
+ BOOST_TEST(*it2 == vec[0]);
+ vec.push_back(*it1);
+
+ ++it1;
+ BOOST_TEST(it1 == fs::directory_iterator());
+
+ BOOST_TEST(*it2 == vec[0]);
       ec.clear();
- dir_itr2.increment(ec);
+ it2.increment(ec);
       BOOST_TEST(!ec);
- BOOST_TEST(dir_itr2 == fs::directory_iterator());
+ BOOST_TEST(it2 != fs::directory_iterator());
+ BOOST_TEST(it1 == fs::directory_iterator());
+ BOOST_TEST(*it2 == vec[1]);
+ ++it2;
+ BOOST_TEST(*it2 == vec[2]);
+ BOOST_TEST(it1 == fs::directory_iterator());
+ ++it2;
+ BOOST_TEST(*it2 == vec[3]);
+ ++it2;
+ BOOST_TEST(it1 == fs::directory_iterator());
+ BOOST_TEST(it2 == fs::directory_iterator());
+
+ // sort vec and check that the right directory entries were found
+ std::sort(vec.begin(), vec.end());
+
+ BOOST_TEST_EQ(vec[0].path().filename().string(), std::string("d1"));
+ BOOST_TEST_EQ(vec[1].path().filename().string(), std::string("d2"));
+ BOOST_TEST_EQ(vec[2].path().filename().string(), std::string("f0"));
+ BOOST_TEST_EQ(vec[3].path().filename().string(), std::string("f1"));
     }
 
- { // *i++ must work to meet the standard's InputIterator requirements
+ { // *i++ must meet the standard's InputIterator requirements
       fs::directory_iterator dir_itr(dir);
- BOOST_TEST(dir_itr->path().filename() == "d1"
- || dir_itr->path().filename() == "d2");
- if (dir_itr->path().filename() == "d1")
- {
- BOOST_TEST((*dir_itr++).path().filename() == "d1");
- BOOST_TEST(dir_itr->path().filename() == "d2");
- }
- else
- {
- // Check C++98 input iterator requirements
- BOOST_TEST((*dir_itr++).path().filename() == "d2");
- // input iterator requirements in the current WP would require this check:
- // BOOST_TEST(implicit_cast<std::string const&>(*dir_itr++).filename() == "d1");
-
- BOOST_TEST(dir_itr->path().filename() == "d1");
- }
+ BOOST_TEST(dir_itr != fs::directory_iterator());
+ fs::path p = dir_itr->path();
+ BOOST_TEST((*dir_itr++).path() == p);
+ BOOST_TEST(dir_itr != fs::directory_iterator());
+ BOOST_TEST(dir_itr->path() != p);
 
       // test case reported in comment to SourceForge bug tracker [937606]
       fs::directory_iterator it(dir);
@@ -415,6 +495,8 @@
       BOOST_TEST(it != fs::directory_iterator());
       const fs::path p2 = (*it++).path();
       BOOST_TEST(p1 != p2);
+ ++it;
+ ++it;
       BOOST_TEST(it == fs::directory_iterator());
     }
 
@@ -457,12 +539,12 @@
     std::cout << "create_hard_link_tests..." << std::endl;
 
     fs::path from_ph(dir / "f3");
- fs::path file_ph(dir / "f1");
+ fs::path f1(dir / "f1");
 
     BOOST_TEST(!fs::exists(from_ph));
- BOOST_TEST(fs::exists(file_ph));
+ BOOST_TEST(fs::exists(f1));
     bool create_hard_link_ok(true);
- try { fs::create_hard_link(file_ph, from_ph); }
+ try { fs::create_hard_link(f1, from_ph); }
     catch (const fs::filesystem_error & ex)
     {
       create_hard_link_ok = false;
@@ -479,10 +561,10 @@
         << " *** For information only ***\n"
            " create_hard_link() succeeded\n";
       BOOST_TEST(fs::exists(from_ph));
- BOOST_TEST(fs::exists(file_ph));
- BOOST_TEST(fs::equivalent(from_ph, file_ph));
+ BOOST_TEST(fs::exists(f1));
+ BOOST_TEST(fs::equivalent(from_ph, f1));
       BOOST_TEST(fs::hard_link_count(from_ph) == 2);
- BOOST_TEST(fs::hard_link_count(file_ph) == 2);
+ BOOST_TEST(fs::hard_link_count(f1) == 2);
     }
 
     // Although tests may be running on a FAT or other file system that does
@@ -503,10 +585,10 @@
     std::cout << "create_symlink_tests..." << std::endl;
 
     fs::path from_ph(dir / "f4");
- fs::path file_ph(dir / "f1");
+ fs::path f1(dir / "f1");
     BOOST_TEST(!fs::exists(from_ph));
- BOOST_TEST(fs::exists(file_ph));
- try { fs::create_symlink(file_ph, from_ph); }
+ BOOST_TEST(fs::exists(f1));
+ try { fs::create_symlink(f1, from_ph); }
     catch (const fs::filesystem_error & ex)
     {
       create_symlink_ok = false;
@@ -524,9 +606,9 @@
            " create_symlink() succeeded\n";
       BOOST_TEST(fs::exists(from_ph));
       BOOST_TEST(fs::is_symlink(from_ph));
- BOOST_TEST(fs::exists(file_ph));
- BOOST_TEST(fs::equivalent(from_ph, file_ph));
- BOOST_TEST(fs::read_symlink(from_ph) == file_ph);
+ BOOST_TEST(fs::exists(f1));
+ BOOST_TEST(fs::equivalent(from_ph, f1));
+ BOOST_TEST(fs::read_symlink(from_ph) == f1);
 
       fs::file_status stat = fs::symlink_status(from_ph);
       BOOST_TEST(fs::exists(stat));
@@ -564,8 +646,8 @@
   {
     std::cout << "rename_tests..." << std::endl;
 
- fs::path file_ph(dir / "f1");
- BOOST_TEST(fs::exists(file_ph));
+ fs::path f1(dir / "f1");
+ BOOST_TEST(fs::exists(f1));
 
     // error: rename a non-existent old file
     BOOST_TEST(!fs::exists(d1 / "f99"));
@@ -576,7 +658,7 @@
     BOOST_TEST(CHECK_EXCEPTION(n1b, ENOENT));
 
     // error: rename an existing file to ""
- renamer n2(file_ph, "");
+ renamer n2(f1, "");
     BOOST_TEST(CHECK_EXCEPTION(n2, ENOENT));
 
     // rename an existing file to an existent file
@@ -622,7 +704,7 @@
     BOOST_TEST(!fs::exists(d2 / "f2"));
     BOOST_TEST(fs::exists(d2 / "f3"));
     BOOST_TEST(!fs::is_directory(d2 / "f3"));
- verify_file(d2 / "f3", "foobar1");
+ verify_file(d2 / "f3", "file-f1");
     fs::rename(d2 / "f3", d1 / "f2");
     BOOST_TEST(fs::exists(d1 / "f2"));
 
@@ -782,19 +864,19 @@
   {
     std::cout << "resize_file_tests..." << std::endl;
 
- const std::string f ("resize_file_test.txt");
+ fs::path p(dir / "resize_file_test.txt");
 
- fs::remove(f);
- create_file(f, "1234567890");
+ fs::remove(p);
+ create_file(p, "1234567890");
 
- BOOST_TEST(fs::exists(f));
- BOOST_TEST_EQ(fs::file_size(f), 10U);
- fs::resize_file(f, 5);
- BOOST_TEST(fs::exists(f));
- BOOST_TEST_EQ(fs::file_size(f), 5U);
- fs::resize_file(f, 15);
- BOOST_TEST(fs::exists(f));
- BOOST_TEST_EQ(fs::file_size(f), 15U);
+ BOOST_TEST(fs::exists(p));
+ BOOST_TEST_EQ(fs::file_size(p), 10U);
+ fs::resize_file(p, 5);
+ BOOST_TEST(fs::exists(p));
+ BOOST_TEST_EQ(fs::file_size(p), 5U);
+ fs::resize_file(p, 15);
+ BOOST_TEST(fs::exists(p));
+ BOOST_TEST_EQ(fs::file_size(p), 15U);
 
     error_code ec;
     fs::resize_file("no such file", 15, ec);
@@ -892,13 +974,13 @@
     std::cout << "remove_tests..." << std::endl;
 
     // remove() file
- fs::path file_ph = dir / "shortlife";
- BOOST_TEST(!fs::exists(file_ph));
- create_file(file_ph, "");
- BOOST_TEST(fs::exists(file_ph));
- BOOST_TEST(!fs::is_directory(file_ph));
- BOOST_TEST(fs::remove(file_ph));
- BOOST_TEST(!fs::exists(file_ph));
+ fs::path f1 = dir / "shortlife";
+ BOOST_TEST(!fs::exists(f1));
+ create_file(f1, "");
+ BOOST_TEST(fs::exists(f1));
+ BOOST_TEST(!fs::is_directory(f1));
+ BOOST_TEST(fs::remove(f1));
+ BOOST_TEST(!fs::exists(f1));
     BOOST_TEST(!fs::remove("no-such-file"));
     BOOST_TEST(!fs::remove("no-such-directory/no-such-file"));
 
@@ -958,25 +1040,25 @@
     BOOST_TEST(!fs::is_symlink(link));
 
     // remove() symbolic link to file
- fs::path file_ph = "link_target";
- fs::remove(file_ph); // remove any residue from past tests
- BOOST_TEST(!fs::exists(file_ph));
- create_file(file_ph, "");
- BOOST_TEST(fs::exists(file_ph));
- BOOST_TEST(!fs::is_directory(file_ph));
- BOOST_TEST(fs::is_regular_file(file_ph));
+ fs::path f1 = "link_target";
+ fs::remove(f1); // remove any residue from past tests
+ BOOST_TEST(!fs::exists(f1));
+ create_file(f1, "");
+ BOOST_TEST(fs::exists(f1));
+ BOOST_TEST(!fs::is_directory(f1));
+ BOOST_TEST(fs::is_regular_file(f1));
     link = "non_dangling_link";
- fs::create_symlink(file_ph, link);
+ fs::create_symlink(f1, link);
     BOOST_TEST(fs::exists(link));
     BOOST_TEST(!fs::is_directory(link));
     BOOST_TEST(fs::is_regular_file(link));
     BOOST_TEST(fs::is_symlink(link));
     BOOST_TEST(fs::remove(link));
- BOOST_TEST(fs::exists(file_ph));
+ BOOST_TEST(fs::exists(f1));
     BOOST_TEST(!fs::exists(link));
     BOOST_TEST(!fs::is_symlink(link));
- BOOST_TEST(fs::remove(file_ph));
- BOOST_TEST(!fs::exists(file_ph));
+ BOOST_TEST(fs::remove(f1));
+ BOOST_TEST(!fs::exists(f1));
   }
 
   // absolute_tests -----------------------------------------------------------------//
@@ -1055,57 +1137,152 @@
 
  // copy_file_tests -----------------------------------------------------------------//
 
- void copy_file_tests(const fs::path& file_ph, const fs::path& d1)
+ void copy_file_tests(const fs::path& f1, const fs::path& d1)
   {
     std::cout << "copy_file_tests..." << std::endl;
 
- BOOST_TEST(fs::exists(file_ph));
+ BOOST_TEST(fs::exists(f1));
     fs::remove(d1 / "f2"); // remove possible residue from prior testing
     BOOST_TEST(fs::exists(d1));
     BOOST_TEST(!fs::exists(d1 / "f2"));
- std::cout << " copy " << file_ph << " to " << d1 / "f2" << std::endl;
- fs::copy_file(file_ph, d1 / "f2");
+ std::cout << " copy " << f1 << " to " << d1 / "f2" << std::endl;
+ fs::copy_file(f1, d1 / "f2");
     std::cout << " copy complete" << std::endl;
- BOOST_TEST(fs::exists(file_ph));
+ BOOST_TEST(fs::exists(f1));
     BOOST_TEST(fs::exists(d1 / "f2"));
     BOOST_TEST(!fs::is_directory(d1 / "f2"));
- verify_file(d1 / "f2", "foobar1");
+ verify_file(d1 / "f2", "file-f1");
 
     bool copy_ex_ok = false;
- try { fs::copy_file(file_ph, d1 / "f2"); }
+ try { fs::copy_file(f1, d1 / "f2"); }
     catch (const fs::filesystem_error &) { copy_ex_ok = true; }
     BOOST_TEST(copy_ex_ok);
 
     copy_ex_ok = false;
- try { fs::copy_file(file_ph, d1 / "f2", fs::copy_option::fail_if_exists); }
+ try { fs::copy_file(f1, d1 / "f2", fs::copy_option::fail_if_exists); }
     catch (const fs::filesystem_error &) { copy_ex_ok = true; }
     BOOST_TEST(copy_ex_ok);
 
     copy_ex_ok = true;
- try { fs::copy_file(file_ph, d1 / "f2", fs::copy_option::overwrite_if_exists); }
+ try { fs::copy_file(f1, d1 / "f2", fs::copy_option::overwrite_if_exists); }
     catch (const fs::filesystem_error &) { copy_ex_ok = false; }
     BOOST_TEST(copy_ex_ok);
   }
 
+ // symlink_status_tests -------------------------------------------------------------//
+
+ void symlink_status_tests()
+ {
+ std::cout << "symlink_status_tests..." << std::endl;
+
+ boost::system::error_code ec;
+
+ fs::path dangling_sym(dir / "dangling-sym");
+ fs::path dangling_directory_sym(dir / "dangling-directory-sym");
+ fs::path sym_d1(dir / "sym-d1");
+ fs::path symsym_d1(dir / "symsym-d1");
+ fs::path sym_f1(dir / "sym-f1");
+ fs::path symsym_f1(dir / "symsym-f1");
+ fs::create_symlink("does not exist", dangling_sym);
+ fs::create_directory_symlink("does not exist", dangling_directory_sym);
+ fs::create_directory_symlink(d1, sym_d1);
+ fs::create_directory_symlink(sym_d1, symsym_d1);
+ fs::create_symlink(f1, sym_f1);
+ fs::create_symlink(sym_f1, symsym_f1);
+
+ // verify all cases detected as symlinks
+ BOOST_TEST_EQ(fs::symlink_status(dangling_sym, ec).type(), fs::symlink_file);
+ BOOST_TEST_EQ(fs::symlink_status(dangling_directory_sym, ec).type(), fs::symlink_file);
+ BOOST_TEST_EQ(fs::symlink_status(sym_d1, ec).type(), fs::symlink_file);
+ BOOST_TEST_EQ(fs::symlink_status(symsym_d1, ec).type(), fs::symlink_file);
+ BOOST_TEST_EQ(fs::symlink_status(sym_f1, ec).type(), fs::symlink_file);
+ BOOST_TEST_EQ(fs::symlink_status(symsym_f1, ec).type(), fs::symlink_file);
+
+ // verify all cases resolve to the (possibly recursive) symlink target
+ BOOST_TEST_EQ(fs::status(dangling_sym, ec).type(), fs::file_not_found);
+ BOOST_TEST_EQ(fs::status(dangling_directory_sym, ec).type(), fs::file_not_found);
+
+ BOOST_TEST_EQ(fs::status(sym_d1, ec).type(), fs::directory_file);
+ BOOST_TEST_EQ(fs::status(sym_d1 / "d1f1", ec).type(), fs::regular_file);
+ BOOST_TEST_EQ(fs::status(symsym_d1, ec).type(), fs::directory_file);
+ BOOST_TEST_EQ(fs::status(symsym_d1 / "d1f1", ec).type(), fs::regular_file);
+ BOOST_TEST_EQ(fs::status(sym_f1, ec).type(), fs::regular_file);
+ BOOST_TEST_EQ(fs::status(symsym_f1, ec).type(), fs::regular_file);
+
+#ifdef BOOST_WINDOWS_API
+
+ // On Windows, telling if a filesystem entry is a symlink, rather than some other
+ // kind of reparse point such as a junction, requires some truely baroque code.
+ // See ticket #4663, filesystem objects falsely identified as symlinks.
+ // This test checks two directory entries created by Windows itself to verify
+ // is_symlink() works correctly. Try "dir /A %HOMEPATH%\.." from the command line to
+ // verify this test is valid on your version of Windows. It only works on Vista and
+ // later.
+
+ fs::path users(getenv("HOMEDRIVE"));
+ BOOST_TEST(!users.empty());
+ users /= "\\Users";
+ BOOST_TEST(fs::exists(users));
+ BOOST_TEST(fs::exists(users/"All Users"));
+ BOOST_TEST(fs::exists(users/"Default User"));
+ BOOST_TEST(fs::is_symlink(users/"All Users")); // dir /A reports <SYMLINKD>
+ BOOST_TEST(!fs::is_symlink(users/"Default User")); // dir /A reports <JUNCTION> <JUNCTION>
+
+#endif
+ }
+
+ // copy_symlink_tests ---------------------------------------------------------------//
+
+ void copy_symlink_tests(const fs::path& f1, const fs::path& d1)
+ {
+ std::cout << "copy_symlink_tests..." << std::endl;
+
+ BOOST_TEST(fs::exists(f1));
+ BOOST_TEST(fs::exists(d1));
+ fs::path sym1(d1 / "symlink1");
+ fs::remove(sym1); // remove possible residue from prior testing
+ fs::create_symlink(f1, sym1);
+ BOOST_TEST(fs::exists(sym1));
+ BOOST_TEST(fs::is_symlink(sym1));
+ fs::path sym2(d1 / "symlink2");
+ fs::copy_symlink(sym1, sym2);
+ BOOST_TEST(fs::exists(sym2));
+ BOOST_TEST(fs::is_symlink(sym2));
+ //fs::path sym3(d1 / "symlink3");
+ //fs::copy(sym1, sym3);
+ //BOOST_TEST(fs::exists(sym3));
+ //BOOST_TEST(fs::is_symlink(sym3));
+
+ bool copy_ex_ok = false;
+ try { fs::copy_symlink("no-such-file", "new-symlink1"); }
+ catch (const fs::filesystem_error &) { copy_ex_ok = true; }
+ BOOST_TEST(copy_ex_ok);
+
+ copy_ex_ok = false;
+ try { fs::copy_symlink(f1, "new-symlink2"); } // should fail; f1 not symlink
+ catch (const fs::filesystem_error &) { copy_ex_ok = true; }
+ BOOST_TEST(copy_ex_ok);
+ }
+
   // write_time_tests ----------------------------------------------------------------//
 
   void write_time_tests(const fs::path& dir)
   {
     std::cout << "write_time_tests..." << std::endl;
 
- fs::path file_ph = dir / "foobar2";
- create_file(file_ph, "foobar2");
- BOOST_TEST(fs::exists(file_ph));
- BOOST_TEST(!fs::is_directory(file_ph));
- BOOST_TEST(fs::is_regular_file(file_ph));
- BOOST_TEST(fs::file_size(file_ph) == 7);
- verify_file(file_ph, "foobar2");
+ fs::path f1 = dir / "foobar2";
+ create_file(f1, "foobar2");
+ BOOST_TEST(fs::exists(f1));
+ BOOST_TEST(!fs::is_directory(f1));
+ BOOST_TEST(fs::is_regular_file(f1));
+ BOOST_TEST(fs::file_size(f1) == 7);
+ verify_file(f1, "foobar2");
 
     // Some file system report last write time as local (FAT), while
     // others (NTFS) report it as UTC. The C standard does not specify
     // if time_t is local or UTC.
 
- std::time_t ft = fs::last_write_time(file_ph);
+ std::time_t ft = fs::last_write_time(f1);
     std::cout << "\n UTC last_write_time() for a file just created is "
       << std::asctime(std::gmtime(&ft)) << std::endl;
 
@@ -1113,15 +1290,15 @@
     std::cout << "\n Year is " << tmp->tm_year << std::endl;
     --tmp->tm_year;
     std::cout << " Change year to " << tmp->tm_year << std::endl;
- fs::last_write_time(file_ph, std::mktime(tmp));
- std::time_t ft2 = fs::last_write_time(file_ph);
+ fs::last_write_time(f1, std::mktime(tmp));
+ std::time_t ft2 = fs::last_write_time(f1);
     std::cout << " last_write_time() for the file is now "
       << std::asctime(std::gmtime(&ft2)) << std::endl;
- BOOST_TEST(ft != fs::last_write_time(file_ph));
+ BOOST_TEST(ft != fs::last_write_time(f1));
 
     std::cout << "\n Reset to current time" << std::endl;
- fs::last_write_time(file_ph, ft);
- double time_diff = std::difftime(ft, fs::last_write_time(file_ph));
+ fs::last_write_time(f1, ft);
+ double time_diff = std::difftime(ft, fs::last_write_time(f1));
     std::cout
       << " original last_write_time() - current last_write_time() is "
       << time_diff << " seconds" << std::endl;
@@ -1220,20 +1397,20 @@
 
   // equivalent_tests ----------------------------------------------------------------//
 
- void equivalent_tests(const fs::path& file_ph)
+ void equivalent_tests(const fs::path& f1)
   {
     std::cout << "equivalent_tests..." << std::endl;
 
     BOOST_TEST(CHECK_EXCEPTION(bad_equivalent, ENOENT));
- BOOST_TEST(fs::equivalent(file_ph, dir / "f1"));
+ BOOST_TEST(fs::equivalent(f1, dir / "f1"));
     BOOST_TEST(fs::equivalent(dir, d1 / ".."));
- BOOST_TEST(!fs::equivalent(file_ph, dir));
- BOOST_TEST(!fs::equivalent(dir, file_ph));
+ BOOST_TEST(!fs::equivalent(f1, dir));
+ BOOST_TEST(!fs::equivalent(dir, f1));
     BOOST_TEST(!fs::equivalent(d1, d2));
     BOOST_TEST(!fs::equivalent(dir, ng));
     BOOST_TEST(!fs::equivalent(ng, dir));
- BOOST_TEST(!fs::equivalent(file_ph, ng));
- BOOST_TEST(!fs::equivalent(ng, file_ph));
+ BOOST_TEST(!fs::equivalent(f1, ng));
+ BOOST_TEST(!fs::equivalent(ng, f1));
   }
 
   // _tests --------------------------------------------------------------------------//
@@ -1302,57 +1479,42 @@
   current_directory_tests();
   space_tests();
 
- // create directory d1, used by subsequent tests
- BOOST_TEST(!fs::create_directory(dir));
- BOOST_TEST(!fs::is_symlink(dir));
- BOOST_TEST(!fs::is_symlink("nosuchfileordirectory"));
- d1 = dir / "d1";
- BOOST_TEST(fs::create_directory(d1));
- BOOST_TEST(fs::exists(d1));
- BOOST_TEST(fs::is_directory(d1));
- BOOST_TEST(fs::is_empty(d1));
+ // create a directory tree that can be used by subsequent tests
+ //
+ // dir
+ // d1
+ // d1f1 // an empty file
+ // f0 // an empty file
+ // f1 // a file containing "file f1"
+ //
+ create_tree();
 
   status_of_nonexistent_tests();
   status_error_reporting_tests();
   directory_iterator_tests();
   create_directories_tests(); // must run AFTER directory_iterator_tests
 
- // create an empty file named "f0", used in subsequent tests
- fs::path file_ph(dir / "f0");
- create_file(file_ph, "");
- BOOST_TEST(fs::exists(file_ph));
- BOOST_TEST(!fs::is_directory(file_ph));
- BOOST_TEST(fs::is_regular_file(file_ph));
- BOOST_TEST(fs::is_empty(file_ph));
- BOOST_TEST(fs::file_size(file_ph) == 0);
- BOOST_TEST(fs::hard_link_count(file_ph) == 1);
-
- bad_create_directory_path = file_ph;
+ bad_create_directory_path = f1;
   BOOST_TEST(CHECK_EXCEPTION(bad_create_directory, EEXIST));
- fs::file_status stat = fs::status(file_ph);
+ fs::file_status stat = fs::status(f1);
   BOOST_TEST(fs::status_known(stat));
   BOOST_TEST(fs::exists(stat));
   BOOST_TEST(!fs::is_directory(stat));
   BOOST_TEST(fs::is_regular_file(stat));
   BOOST_TEST(!fs::is_other(stat));
   BOOST_TEST(!fs::is_symlink(stat));
-
- // create a file named "f1", used in subsequent tests
- file_ph = dir / "f1";
- create_file(file_ph, "foobar1");
-
- BOOST_TEST(fs::exists(file_ph));
- BOOST_TEST(!fs::is_directory(file_ph));
- BOOST_TEST(fs::is_regular_file(file_ph));
- BOOST_TEST(fs::file_size(file_ph) == 7);
- verify_file(file_ph, "foobar1");
   
- equivalent_tests(file_ph);
+ equivalent_tests(f1);
   create_hard_link_tests();
   create_symlink_tests();
   resize_file_tests();
   absolute_tests();
- copy_file_tests(file_ph, d1);
+ copy_file_tests(f1, d1);
+ if (create_symlink_ok) // only if symlinks supported
+ {
+ symlink_status_tests();
+ copy_symlink_tests(f1, d1);
+ }
   rename_tests();
   remove_tests(dir);
   if (create_symlink_ok) // only if symlinks supported
@@ -1376,4 +1538,3 @@
   std::cout << "returning from main()" << std::endl;
   return ::boost::report_errors();
 } // main
-

Modified: branches/release/libs/filesystem/v3/test/operations_unit_test.cpp
==============================================================================
--- branches/release/libs/filesystem/v3/test/operations_unit_test.cpp (original)
+++ branches/release/libs/filesystem/v3/test/operations_unit_test.cpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -7,6 +7,12 @@
 
 // Library home page: http://www.boost.org/libs/filesystem
 
+// ------------------------------------------------------------------------------------//
+
+// This program is misnamed - it is really a smoke test rather than a unit_test
+
+// ------------------------------------------------------------------------------------//
+
 #define BOOST_FILESYSTEM_VERSION 3
 
 #include <boost/config.hpp>

Modified: branches/release/libs/filesystem/v3/test/path_test.cpp
==============================================================================
--- branches/release/libs/filesystem/v3/test/path_test.cpp (original)
+++ branches/release/libs/filesystem/v3/test/path_test.cpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -692,6 +692,7 @@
 
     // extension() tests not otherwise covered
     BOOST_TEST(path("a/b").extension() == "");
+ BOOST_TEST(path("a.b/c").extension() == "");
     BOOST_TEST(path("a/b.txt").extension() == ".txt");
     BOOST_TEST(path("a/b.").extension() == ".");
     BOOST_TEST(path("a.b.c").extension() == ".c");
@@ -1561,7 +1562,9 @@
     BOOST_TEST(path("a").replace_extension(".txt") == "a.txt");
     BOOST_TEST(path("a").replace_extension("txt") == "a");
     BOOST_TEST(path("a.b.txt").replace_extension(".tex") == "a.b.tex");
- BOOST_TEST(path("a.b.txt").replace_extension("tex") == "a.b");
+ BOOST_TEST(path("a.b.txt").replace_extension("tex") == "a.b");
+ BOOST_TEST(path("a/b").replace_extension(".c") == "a/b.c");
+ BOOST_TEST_EQ(path("a.txt/b").replace_extension(".c"), "a.txt/b.c"); // ticket 4702
   }
 
 } // unnamed namespace

Modified: branches/release/libs/filesystem/v3/test/path_unit_test.cpp
==============================================================================
--- branches/release/libs/filesystem/v3/test/path_unit_test.cpp (original)
+++ branches/release/libs/filesystem/v3/test/path_unit_test.cpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -41,11 +41,14 @@
 #include <boost/filesystem/detail/utf8_codecvt_facet.hpp> // for imbue tests
 #include "test_codecvt.hpp" // for codecvt arg tests
 #include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr.hpp> // used constructor tests
 
 #include <iostream>
 #include <iomanip>
 #include <sstream>
 #include <string>
+#include <cstring>
+#include <cwchar>
 #include <locale>
 #include <list>
 
@@ -144,6 +147,11 @@
   std::vector<char> v; // see main() for initialization to f, u, z
   std::vector<wchar_t> wv; // see main() for initialization to w, f, u, z
 
+ class Base {};
+ class Derived : public Base {};
+ void fun(const boost::filesystem::path&) {}
+ void fun(const boost::shared_ptr< Base >&) {}
+
   // test_constructors ---------------------------------------------------------------//
 
   void test_constructors()
@@ -191,6 +199,18 @@
     PATH_IS(x7, L"array wchar_t");
     BOOST_TEST_EQ(x7.native().size(), 13U);
 
+ char char_array[100];
+ std::strcpy(char_array, "big array char");
+ path x6o(char_array); // array char, only partially full
+ PATH_IS(x6o, L"big array char");
+ BOOST_TEST_EQ(x6o.native().size(), 14U);
+
+ wchar_t wchar_array[100];
+ std::wcscpy(wchar_array, L"big array wchar_t");
+ path x7o(wchar_array); // array char, only partially full
+ PATH_IS(x7o, L"big array wchar_t");
+ BOOST_TEST_EQ(x7o.native().size(), 17U);
+
     path x8(s.c_str()); // const char* null terminated
     PATH_IS(x8, L"string");
     BOOST_TEST_EQ(x8.native().size(), 6U);
@@ -210,6 +230,10 @@
 
     // easy-to-make coding errors
     // path e1(x0, path::codecvt()); // fails to compile, and that is OK
+
+ boost::shared_ptr< Derived > pDerived( new Derived() );
+ fun( pDerived ); // tests constructor member template enable_if working correctly;
+ // will fail to compile if enable_if not taking path off the table
   }
 
   path x;

Modified: branches/release/libs/filesystem/v3/test/test_codecvt.hpp
==============================================================================
--- branches/release/libs/filesystem/v3/test/test_codecvt.hpp (original)
+++ branches/release/libs/filesystem/v3/test/test_codecvt.hpp 2010-10-16 09:09:25 EDT (Sat, 16 Oct 2010)
@@ -11,7 +11,8 @@
 #define BOOST_FILESYSTEM3_TEST_CODECVT_HPP
 
 #include <boost/filesystem/v3/config.hpp>
-#include <locale>
+#include <locale>
+#include <cwchar> // for mbstate_t
 
   //------------------------------------------------------------------------------------//
   // //


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk