Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r74950 - in trunk: boost/filesystem/v3 libs/filesystem/v3/src libs/filesystem/v3/test libs/filesystem/v3/test/msvc10
From: bdawes_at_[hidden]
Date: 2011-10-15 12:02:23


Author: bemandawes
Date: 2011-10-15 12:02:20 EDT (Sat, 15 Oct 2011)
New Revision: 74950
URL: http://svn.boost.org/trac/boost/changeset/74950

Log:
Add support for permissions. Docs to follow.
Text files modified:
   trunk/boost/filesystem/v3/operations.hpp | 140 +++++++++++++++++++++---
   trunk/libs/filesystem/v3/src/operations.cpp | 226 +++++++++++++++++++++++++++++++--------
   trunk/libs/filesystem/v3/test/msvc10/filesystem-v3.sln | 10 +
   trunk/libs/filesystem/v3/test/operations_test.cpp | 83 ++++++++++++--
   trunk/libs/filesystem/v3/test/operations_unit_test.cpp | 58 +++++++---
   trunk/libs/filesystem/v3/test/path_test.cpp | 2
   6 files changed, 422 insertions(+), 97 deletions(-)

Modified: trunk/boost/filesystem/v3/operations.hpp
==============================================================================
--- trunk/boost/filesystem/v3/operations.hpp (original)
+++ trunk/boost/filesystem/v3/operations.hpp 2011-10-15 12:02:20 EDT (Sat, 15 Oct 2011)
@@ -55,9 +55,7 @@
   {
 
 //--------------------------------------------------------------------------------------//
-// //
-// support classes and enums //
-// //
+// file_type //
 //--------------------------------------------------------------------------------------//
 
   enum file_type
@@ -82,27 +80,96 @@
     _detail_directory_symlink // internal use only; never exposed to users
   };
 
+//--------------------------------------------------------------------------------------//
+// perms //
+//--------------------------------------------------------------------------------------//
+
+ enum perms
+ {
+ no_perms = 0, // file_not_found is no_perms rather than perms_not_known
+
+ // POSIX equivalent macros given in comments.
+ // Values are from POSIX and are given in octal per the POSIX standard.
+
+ // permission bits
+
+ owner_read = 0400, // S_IRUSR, Read permission, owner
+ owner_write = 0200, // S_IWUSR, Write permission, owner
+ owner_exe = 0100, // S_IXUSR, Execute/search permission, owner
+ owner_all = 0700, // S_IRWXU, Read, write, execute/search by owner
+
+ group_read = 040, // S_IRGRP, Read permission, group
+ group_write = 020, // S_IWGRP, Write permission, group
+ group_exe = 010, // S_IXGRP, Execute/search permission, group
+ group_all = 070, // S_IRWXG, Read, write, execute/search by group
+
+ others_read = 04, // S_IROTH, Read permission, others
+ others_write = 02, // S_IWOTH, Write permission, others
+ others_exe = 01, // S_IXOTH, Execute/search permission, others
+ others_all = 07, // S_IRWXO, Read, write, execute/search by others
+
+ all_all = owner_all|group_all|others_all, // 0777
+
+ // other POSIX bits
+
+ set_uid_on_exe = 04000, // S_ISUID, Set-user-ID on execution
+ set_gid_on_exe = 02000, // S_ISGID, Set-group-ID on execution
+ sticky_bit = 01000, // S_ISVTX,
+ // (POSIX XSI) On directories, restricted deletion flag
+ // (V7) 'sticky bit': save swapped text even after use
+ // (SunOS) On non-directories: don't cache this file
+ // (SVID-v4.2) On directories: restricted deletion flag
+ // Also see http://en.wikipedia.org/wiki/Sticky_bit
+
+ perms_mask = all_all|set_uid_on_exe|set_gid_on_exe|sticky_bit, // 07777
+
+ perms_not_known = 0xFFFF, // present when directory_entry cache not loaded
+
+ // options for permissions() function
+
+ add_perms = 0x1000, // adds the given permission bits to the current bits
+ remove_perms = 0x2000, // removes the given permission bits from the current bits;
+ // choose add_perms or remove_perms, not both; if neither add_perms
+ // nor remove_perms is given, replace the current bits with
+ // the given bits.
+
+ symlink_perms = 0x4000 // on POSIX, don't resolve symlinks; implied on Windows
+ };
+
+ BOOST_BITMASK(perms);
+
+//--------------------------------------------------------------------------------------//
+// file_status //
+//--------------------------------------------------------------------------------------//
+
   class BOOST_FILESYSTEM_DECL file_status
   {
   public:
- file_status() : m_value(status_error) {}
- explicit file_status(file_type v) : m_value(v) {}
-
- void type(file_type v) { m_value = v; }
- file_type type() const { return m_value; }
+ file_status() : m_value(status_error), m_perms(perms_not_known) {}
+ explicit file_status(file_type v, perms prms = perms_not_known)
+ : m_value(v), m_perms(prms) {}
+
+ // observers
+ file_type type() const { return m_value; }
+ perms permissions() const { return m_perms; }
+
+ // modifiers
+ void type(file_type v) { m_value = v; }
+ void permissions(perms prms) { m_perms = prms; }
 
- bool operator==(const file_status& rhs) const { return type() == rhs.type(); }
+ bool operator==(const file_status& rhs) const { return type() == rhs.type() &&
+ permissions() == rhs.permissions(); }
     bool operator!=(const file_status& rhs) const { return !(*this == rhs); }
 
   private:
- // the internal representation is unspecified so that additional state
- // information such as permissions can be added in the future; this
- // implementation just uses file_type as the internal representation
-
- file_type m_value;
+ file_type m_value;
+ enum perms m_perms;
   };
 
- inline bool status_known(file_status f) { return f.type() != status_error; }
+ inline bool type_present(file_status f) { return f.type() != status_error; }
+ inline bool permissions_present(file_status f)
+ {return f.permissions() != perms_not_known;}
+ inline bool status_known(file_status f) { return type_present(f) && permissions_present(f); }
   inline bool exists(file_status f) { return f.type() != status_error
                                                 && f.type() != file_not_found; }
   inline bool is_regular_file(file_status f){ return f.type() == regular_file; }
@@ -159,7 +226,7 @@
     bool create_directory(const path& p, system::error_code* ec=0);
     BOOST_FILESYSTEM_DECL
     void create_directory_symlink(const path& to, const path& from,
- system::error_code* ec=0);
+ system::error_code* ec=0);
     BOOST_FILESYSTEM_DECL
     void create_hard_link(const path& to, const path& from, system::error_code* ec=0);
     BOOST_FILESYSTEM_DECL
@@ -178,7 +245,9 @@
     std::time_t last_write_time(const path& p, system::error_code* ec=0);
     BOOST_FILESYSTEM_DECL
     void last_write_time(const path& p, const std::time_t new_time,
- system::error_code* ec=0);
+ system::error_code* ec=0);
+ BOOST_FILESYSTEM_DECL
+ void permissions(const path& p, perms prms, system::error_code* ec=0);
     BOOST_FILESYSTEM_DECL
     path read_symlink(const path& p, system::error_code* ec=0);
     BOOST_FILESYSTEM_DECL
@@ -280,7 +349,7 @@
   path canonical(const path& p, const path& base, system::error_code& ec)
                                        {return detail::canonical(p, base, &ec);}
 
- # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
+# ifndef BOOST_FILESYSTEM_NO_DEPRECATED
   inline
   path complete(const path& p)
   {
@@ -410,6 +479,13 @@
   void last_write_time(const path& p, const std::time_t new_time, system::error_code& ec)
                                        {detail::last_write_time(p, new_time, &ec);}
   inline
+ void permissions(const path& p, perms prms)
+ {detail::permissions(p, prms);}
+ inline
+ void permissions(const path& p, perms prms, system::error_code& ec)
+ {detail::permissions(p, prms, &ec);}
+
+ inline
   path read_symlink(const path& p) {return detail::read_symlink(p);}
 
   inline
@@ -1000,6 +1076,30 @@
 {
   namespace filesystem
   {
+ // permissions
+ using filesystem3::no_perms;
+ using filesystem3::owner_read;
+ using filesystem3::owner_write;
+ using filesystem3::owner_exe;
+ using filesystem3::owner_all;
+ using filesystem3::group_read;
+ using filesystem3::group_write;
+ using filesystem3::group_exe;
+ using filesystem3::group_all;
+ using filesystem3::others_read;
+ using filesystem3::others_write;
+ using filesystem3::others_exe;
+ using filesystem3::others_all;
+ using filesystem3::all_all;
+ using filesystem3::set_uid_on_exe;
+ using filesystem3::set_gid_on_exe;
+ using filesystem3::sticky_bit;
+ using filesystem3::perms_mask;
+ using filesystem3::perms_not_known;
+ using filesystem3::add_perms;
+ using filesystem3::remove_perms;
+ using filesystem3::symlink_perms;
+
     using filesystem3::absolute;
     using filesystem3::block_file;
     using filesystem3::canonical;
@@ -1034,6 +1134,9 @@
     using filesystem3::is_regular_file;
     using filesystem3::is_symlink;
     using filesystem3::last_write_time;
+ using filesystem3::permissions;
+ using filesystem3::permissions_present;
+ using filesystem3::perms;
     using filesystem3::read_symlink;
     using filesystem3::recursive_directory_iterator;
     using filesystem3::regular_file;
@@ -1053,6 +1156,7 @@
     using filesystem3::symlink_status;
     using filesystem3::system_complete;
     using filesystem3::temp_directory_path;
+ using filesystem3::type_present;
     using filesystem3::type_unknown;
     using filesystem3::unique_path;
 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED

Modified: trunk/libs/filesystem/v3/src/operations.cpp
==============================================================================
--- trunk/libs/filesystem/v3/src/operations.cpp (original)
+++ trunk/libs/filesystem/v3/src/operations.cpp 2011-10-15 12:02:20 EDT (Sat, 15 Oct 2011)
@@ -69,6 +69,7 @@
 namespace fs = boost::filesystem3;
 using boost::filesystem3::path;
 using boost::filesystem3::filesystem_error;
+using boost::filesystem3::perms;
 using boost::system::error_code;
 using boost::system::error_category;
 using boost::system::system_category;
@@ -107,6 +108,7 @@
       // See MinGW's windef.h
 # define WINVER 0x501
 # endif
+# include <io.h>
 # include <windows.h>
 # include <winnt.h>
 # if !defined(_WIN32_WINNT)
@@ -247,12 +249,6 @@
 namespace
 {
 
-# ifdef BOOST_POSIX_API
- const char dot = '.';
-# else
- 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;
@@ -414,6 +410,8 @@
 // //
 //--------------------------------------------------------------------------------------//
 
+ const char dot = '.';
+
   bool not_found_error(int errval)
   {
     return errno == ENOENT || errno == ENOTDIR;
@@ -490,6 +488,8 @@
 // //
 //--------------------------------------------------------------------------------------//
 
+ const wchar_t dot = L'.';
+
   bool not_found_error(int errval)
   {
     return errval == ERROR_FILE_NOT_FOUND
@@ -502,6 +502,19 @@
       || errval == ERROR_BAD_NETPATH; // "//nosuch" on Win32
   }
 
+ perms make_permissions(const path& p, DWORD attr)
+ {
+ perms prms = fs::owner_read | fs::group_read | fs::others_read;
+ if ((attr & FILE_ATTRIBUTE_READONLY) == 0)
+ prms |= fs::owner_write | fs::group_write | fs::others_write;
+ if (_stricmp(p.extension().string().c_str(), ".exe") == 0
+ || _stricmp(p.extension().string().c_str(), ".com") == 0
+ || _stricmp(p.extension().string().c_str(), ".bat") == 0
+ || _stricmp(p.extension().string().c_str(), ".cmd") == 0)
+ prms |= fs::owner_exe | fs::group_exe | fs::others_exe;
+ return prms;
+ }
+
   // these constants come from inspecting some Microsoft sample code
   std::time_t to_time_t(const FILETIME & ft)
   {
@@ -590,7 +603,7 @@
 
     if (not_found_error(errval))
     {
- return fs::file_status(fs::file_not_found);
+ return fs::file_status(fs::file_not_found, fs::no_perms);
     }
     else if ((errval == ERROR_SHARING_VIOLATION))
     {
@@ -755,6 +768,21 @@
 # endif
   }
 
+# ifdef BOOST_POSIX_API
+ const perms active_bits(all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit);
+ inline mode_t mode_cast(perms prms) { return prms & active_bits; }
+# else
+ inline int mode_cast(perms prms)
+ {
+ // Windows _wchmod() can only make a file read-only and there is only one
+ // such attribute bit for the file. Files are always readable. Get over it.
+ return (prms & (owner_write|group_write|others_write)
+ ? _S_IREAD | _S_IWRITE
+ : _S_IREAD
+ );
+ }
+# endif
+
   BOOST_FILESYSTEM_DECL
   path canonical(const path& p, const path& base, system::error_code* ec)
   {
@@ -1330,6 +1358,62 @@
   }
 
   BOOST_FILESYSTEM_DECL
+ void permissions(const path& p, perms prms, system::error_code* ec)
+ {
+ BOOST_ASSERT_MSG(!((prms & add_perms) && (prms & remove_perms)),
+ "add_perms and remove_perms are mutually exclusive");
+
+ if ((prms & add_perms) && (prms & remove_perms)) // precondition failed
+ return;
+
+ error_code local_ec;
+ file_status current_status((prms & symlink_perms)
+ ? fs::symlink_status(p, local_ec)
+ : fs::status(p, local_ec));
+ if (local_ec)
+ {
+ if (ec == 0)
+ BOOST_FILESYSTEM_THROW(filesystem_error(
+ "boost::filesystem::permissions", p, local_ec));
+ else
+ *ec = local_ec;
+ return;
+ }
+
+ if (prms & add_perms)
+ prms |= current_status.permissions();
+ else if (prms & remove_perms)
+ {
+# ifdef BOOST_WINDOWS_API
+ if (prms & (owner_write|group_write|others_write))
+ prms |= owner_write|group_write|others_write;
+# endif
+ prms = current_status.permissions() & ~prms;
+ }
+
+# ifdef BOOST_POSIX_API
+ // Mac OS X Lion and some other platforms don't support fchmodat()
+# if defined(AT_FDCWD) && defined(AT_SYMLINK_NOFOLLOW)
+ if (::fchmodat(AT_FDCWD, p.c_str(), mode_cast(prms),
+ !(prms & symlink_perms) ? 0 : AT_SYMLINK_NOFOLLOW))
+# else // fallback if fchmodat() not supported
+ if (::chmod(p.c_str(), mode_cast(prms)))
+# endif
+# else
+ if (::_wchmod(p.c_str(), mode_cast(prms))) // if error
+# endif
+ {
+ if (ec == 0)
+ BOOST_FILESYSTEM_THROW(filesystem_error(
+ "boost::filesystem::permissions", p,
+ error_code(errno, system::generic_category())));
+ else
+ ec->assign(errno, system::generic_category());
+ }
+
+ }
+
+ BOOST_FILESYSTEM_DECL
   path read_symlink(const path& p, system::error_code* ec)
   {
     path symlink_path;
@@ -1492,7 +1576,7 @@
 
       if (not_found_error(errno))
       {
- return fs::file_status(fs::file_not_found);
+ return fs::file_status(fs::file_not_found, fs::no_perms);
       }
       if (ec == 0)
         BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
@@ -1501,17 +1585,23 @@
     }
     if (ec != 0) ec->clear();;
     if (S_ISDIR(path_stat.st_mode))
- return fs::file_status(fs::directory_file);
+ return fs::file_status(fs::directory_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     if (S_ISREG(path_stat.st_mode))
- return fs::file_status(fs::regular_file);
+ return fs::file_status(fs::regular_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     if (S_ISBLK(path_stat.st_mode))
- return fs::file_status(fs::block_file);
+ return fs::file_status(fs::block_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     if (S_ISCHR(path_stat.st_mode))
- return fs::file_status(fs::character_file);
+ return fs::file_status(fs::character_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     if (S_ISFIFO(path_stat.st_mode))
- return fs::file_status(fs::fifo_file);
+ return fs::file_status(fs::fifo_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     if (S_ISSOCK(path_stat.st_mode))
- return fs::file_status(fs::socket_file);
+ return fs::file_status(fs::socket_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     return fs::file_status(fs::type_unknown);
 
 # else // Windows
@@ -1522,7 +1612,9 @@
       return process_status_failure(p, ec);
     }
 
- // reparse point handling
+ // reparse point handling;
+ // since GetFileAttributesW does not resolve symlinks, try to open a file
+ // handle to discover if the file exists
     if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
     {
       handle_wrapper h(
@@ -1540,13 +1632,13 @@
       }
 
       if (!is_reparse_point_a_symlink(p))
- return file_status(reparse_file);
+ return file_status(reparse_file, make_permissions(p, attr));
     }
 
     if (ec != 0) ec->clear();
     return (attr & FILE_ATTRIBUTE_DIRECTORY)
- ? file_status(directory_file)
- : file_status(regular_file);
+ ? file_status(directory_file, make_permissions(p, attr))
+ : file_status(regular_file, make_permissions(p, attr));
 
 # endif
   }
@@ -1564,7 +1656,7 @@
 
       if (errno == ENOENT || errno == ENOTDIR) // these are not errors
       {
- return fs::file_status(fs::file_not_found);
+ return fs::file_status(fs::file_not_found, fs::no_perms);
       }
       if (ec == 0)
         BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
@@ -1573,19 +1665,26 @@
     }
     if (ec != 0) ec->clear();
     if (S_ISREG(path_stat.st_mode))
- return fs::file_status(fs::regular_file);
+ return fs::file_status(fs::regular_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     if (S_ISDIR(path_stat.st_mode))
- return fs::file_status(fs::directory_file);
+ return fs::file_status(fs::directory_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     if (S_ISLNK(path_stat.st_mode))
- return fs::file_status(fs::symlink_file);
+ return fs::file_status(fs::symlink_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     if (S_ISBLK(path_stat.st_mode))
- return fs::file_status(fs::block_file);
+ return fs::file_status(fs::block_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     if (S_ISCHR(path_stat.st_mode))
- return fs::file_status(fs::character_file);
+ return fs::file_status(fs::character_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     if (S_ISFIFO(path_stat.st_mode))
- return fs::file_status(fs::fifo_file);
+ return fs::file_status(fs::fifo_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     if (S_ISSOCK(path_stat.st_mode))
- return fs::file_status(fs::socket_file);
+ return fs::file_status(fs::socket_file,
+ static_cast<perms>(path_stat.st_mode) & fs::perms_mask);
     return fs::file_status(fs::type_unknown);
 
 # else // Windows
@@ -1600,12 +1699,12 @@
 
     if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
       return is_reparse_point_a_symlink(p)
- ? file_status(symlink_file)
- : file_status(reparse_file);
+ ? file_status(symlink_file, make_permissions(p, attr))
+ : file_status(reparse_file, make_permissions(p, attr));
 
     return (attr & FILE_ATTRIBUTE_DIRECTORY)
- ? file_status(directory_file)
- : file_status(regular_file);
+ ? file_status(directory_file, make_permissions(p, attr))
+ : file_status(regular_file, make_permissions(p, attr));
 
 # endif
   }
@@ -1838,8 +1937,8 @@
     dirent * entry(static_cast<dirent *>(buffer));
     dirent * result;
     int return_code;
- if ((return_code = readdir_r_simulator(static_cast<DIR*>(handle),
- entry, &result))!= 0)return error_code(errno, system_category());
+ if ((return_code = readdir_r_simulator(static_cast<DIR*>(handle), entry, &result))!= 0)
+ return error_code(errno, system_category());
     if (result == 0)
       return fs::detail::dir_itr_close(handle, buffer);
     target = entry->d_name;
@@ -1886,7 +1985,7 @@
     if ((handle = ::FindFirstFileW(dirpath.c_str(), &data))
       == INVALID_HANDLE_VALUE)
     {
- handle = 0;
+ handle = 0; // signal eof
       return error_code( (::GetLastError() == ERROR_FILE_NOT_FOUND
                        // Windows Mobile returns ERROR_NO_MORE_FILES; see ticket #3551
                        || ::GetLastError() == ERROR_NO_MORE_FILES)
@@ -1894,12 +1993,28 @@
     }
     target = data.cFileName;
     if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
- // reparse points are complex, so don't try to handle them here
- { sf.type(fs::status_error); symlink_sf.type(fs::status_error); }
- else if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- { sf.type(fs::directory_file); symlink_sf.type(fs::directory_file); }
+ // reparse points are complex, so don't try to handle them here; instead just mark
+ // them as status_error which causes directory_entry caching to call status()
+ // and symlink_status() which do handle reparse points fully
+ {
+ sf.type(fs::status_error);
+ symlink_sf.type(fs::status_error);
+ }
     else
- { sf.type(fs::regular_file); symlink_sf.type(fs::regular_file); }
+ {
+ if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ sf.type(fs::directory_file);
+ symlink_sf.type(fs::directory_file);
+ }
+ else
+ {
+ sf.type(fs::regular_file);
+ symlink_sf.type(fs::regular_file);
+ }
+ sf.permissions(make_permissions(data.cFileName, data.dwFileAttributes));
+ symlink_sf.permissions(sf.permissions());
+ }
     return error_code();
   }
 
@@ -1915,12 +2030,28 @@
     }
     target = data.cFileName;
     if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
- // reparse points are complex, so don't try to handle them here
- { sf.type(fs::status_error); symlink_sf.type(fs::status_error); }
- else if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- { sf.type(fs::directory_file); symlink_sf.type(fs::directory_file); }
+ // reparse points are complex, so don't try to handle them here; instead just mark
+ // them as status_error which causes directory_entry caching to call status()
+ // and symlink_status() which do handle reparse points fully
+ {
+ sf.type(fs::status_error);
+ symlink_sf.type(fs::status_error);
+ }
     else
- { sf.type(fs::regular_file); symlink_sf.type(fs::regular_file); }
+ {
+ if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ sf.type(fs::directory_file);
+ symlink_sf.type(fs::directory_file);
+ }
+ else
+ {
+ sf.type(fs::regular_file);
+ symlink_sf.type(fs::regular_file);
+ }
+ sf.permissions(make_permissions(data.cFileName, data.dwFileAttributes));
+ symlink_sf.permissions(sf.permissions());
+ }
     return error_code();
   }
 #endif
@@ -1975,7 +2106,8 @@
     const path& p, system::error_code* ec)
   {
     if (error(p.empty(), not_found_error_code, p, ec,
- "boost::filesystem::directory_iterator::construct"))return;
+ "boost::filesystem::directory_iterator::construct"))
+ return;
 
     path::string_type filename;
     file_status file_stat, symlink_file_stat;
@@ -1993,11 +2125,11 @@
       return;
     }
     
- if (it.m_imp->handle == 0)it.m_imp.reset(); // eof, so make end iterator
+ if (it.m_imp->handle == 0)
+ it.m_imp.reset(); // eof, so make end iterator
     else // not eof
     {
- it.m_imp->dir_entry.assign(p / filename,
- file_stat, symlink_file_stat);
+ it.m_imp->dir_entry.assign(p / filename, file_stat, symlink_file_stat);
       if (filename[0] == dot // dot or dot-dot
         && (filename.size()== 1
           || (filename[1] == dot

Modified: trunk/libs/filesystem/v3/test/msvc10/filesystem-v3.sln
==============================================================================
--- trunk/libs/filesystem/v3/test/msvc10/filesystem-v3.sln (original)
+++ trunk/libs/filesystem/v3/test/msvc10/filesystem-v3.sln 2011-10-15 12:02:20 EDT (Sat, 15 Oct 2011)
@@ -73,6 +73,12 @@
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "locale_info", "locale_info\locale_info.vcxproj", "{3667C35E-78D5-43D4-AAC2-349145E4341D}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ticket_5850", "ticket_5850\ticket_5850.vcxproj", "{B1FA4137-7B08-4113-9EC0-F3BAFEFBE2B7}"
+ ProjectSection(ProjectDependencies) = postProject
+ {F94CCADD-A90B-480C-A304-C19D015D36B1} = {F94CCADD-A90B-480C-A304-C19D015D36B1}
+ {FFD738F7-96F0-445C-81EA-551665EF53D1} = {FFD738F7-96F0-445C-81EA-551665EF53D1}
+ EndProjectSection
+EndProject
 Global
         GlobalSection(SolutionConfigurationPlatforms) = preSolution
                 Debug|Win32 = Debug|Win32
@@ -167,6 +173,10 @@
                 {3667C35E-78D5-43D4-AAC2-349145E4341D}.Debug|Win32.Build.0 = Debug|Win32
                 {3667C35E-78D5-43D4-AAC2-349145E4341D}.Release|Win32.ActiveCfg = Release|Win32
                 {3667C35E-78D5-43D4-AAC2-349145E4341D}.Release|Win32.Build.0 = Release|Win32
+ {B1FA4137-7B08-4113-9EC0-F3BAFEFBE2B7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B1FA4137-7B08-4113-9EC0-F3BAFEFBE2B7}.Debug|Win32.Build.0 = Debug|Win32
+ {B1FA4137-7B08-4113-9EC0-F3BAFEFBE2B7}.Release|Win32.ActiveCfg = Release|Win32
+ {B1FA4137-7B08-4113-9EC0-F3BAFEFBE2B7}.Release|Win32.Build.0 = Release|Win32
         EndGlobalSection
         GlobalSection(SolutionProperties) = preSolution
                 HideSolutionNode = FALSE

Modified: trunk/libs/filesystem/v3/test/operations_test.cpp
==============================================================================
--- trunk/libs/filesystem/v3/test/operations_test.cpp (original)
+++ trunk/libs/filesystem/v3/test/operations_test.cpp 2011-10-15 12:02:20 EDT (Sat, 15 Oct 2011)
@@ -95,8 +95,10 @@
 {
   typedef int errno_t;
   std::string platform(BOOST_PLATFORM);
- bool report_throws;
+ bool report_throws = false;
   bool cleanup = true;
+ bool skip_long_windows_tests = false;
+
   fs::directory_iterator end_itr;
   fs::path dir;
   fs::path d1;
@@ -113,7 +115,7 @@
 
   const char* temp_dir_name = "v3_operations_test";
 
- void create_file(const fs::path & ph, const std::string & contents)
+ void create_file(const fs::path & ph, const std::string & contents = std::string())
   {
     std::ofstream f(ph.BOOST_FILESYSTEM_C_STR);
     if (!f)
@@ -800,6 +802,45 @@
     fs::create_symlink("doesnotexist", "", ec);
     BOOST_TEST(ec);
   }
+
+ // permissions_tests ---------------------------------------------------------------//
+
+ void permissions_tests()
+ {
+ cout << "permissions_tests..." << endl;
+
+ fs::path p(dir / "permissions.txt");
+ create_file(p);
+
+ if (platform == "POSIX")
+ {
+ cout << " fs::status(p).permissions() " << std::oct << fs::status(p).permissions()
+ << std::dec << endl;
+ BOOST_TEST(fs::status(p).permissions() == 0644);
+ fs::permissions(p, fs::owner_all);
+ BOOST_TEST(fs::status(p).permissions() == fs::owner_all);
+
+ fs::permissions(p, fs::add_perms | fs::group_all);
+ BOOST_TEST(fs::status(p).permissions() == (fs::owner_all | fs::group_all));
+
+ fs::permissions(p, fs::remove_perms | fs::group_all);
+ BOOST_TEST(fs::status(p).permissions() == fs::owner_all);
+
+ // some POSIX platforms cache permissions during directory iteration, some don't
+ // so test that iteration finds the correct permissions
+ for (fs::directory_iterator itr(dir); itr != fs::directory_iterator(); ++itr)
+ if (itr->path().filename() == fs::path("permissions.txt"))
+ BOOST_TEST(itr->status().permissions() == fs::owner_all);
+ }
+ else // Windows
+ {
+ BOOST_TEST(fs::status(p).permissions() == 0666);
+ fs::permissions(p, fs::remove_perms | fs::group_write);
+ BOOST_TEST(fs::status(p).permissions() == 0444);
+ fs::permissions(p, fs::add_perms | fs::group_write);
+ BOOST_TEST(fs::status(p).permissions() == 0666);
+ }
+ }
   
   // rename_tests --------------------------------------------------------------------//
 
@@ -917,6 +958,8 @@
     BOOST_TEST(!fs::is_regular_file(ng));
     BOOST_TEST(!fs::is_symlink(ng));
     fs::file_status stat(fs::status(ng));
+ BOOST_TEST(fs::type_present(stat));
+ BOOST_TEST(fs::permissions_present(stat));
     BOOST_TEST(fs::status_known(stat));
     BOOST_TEST(!fs::exists(stat));
     BOOST_TEST(!fs::is_directory(stat));
@@ -924,6 +967,8 @@
     BOOST_TEST(!fs::is_other(stat));
     BOOST_TEST(!fs::is_symlink(stat));
     stat = fs::status("");
+ BOOST_TEST(fs::type_present(stat));
+ BOOST_TEST(fs::permissions_present(stat));
     BOOST_TEST(fs::status_known(stat));
     BOOST_TEST(!fs::exists(stat));
     BOOST_TEST(!fs::is_directory(stat));
@@ -1059,7 +1104,7 @@
     fs::file_status s = fs::status(p);
     BOOST_TEST(!fs::exists(s));
     BOOST_TEST_EQ(s.type(), fs::file_not_found);
- BOOST_TEST(fs::status_known(s));
+ BOOST_TEST(fs::type_present(s));
     BOOST_TEST(!fs::is_regular_file(s));
     BOOST_TEST(!fs::is_directory(s));
     BOOST_TEST(!fs::is_symlink(s));
@@ -1093,7 +1138,7 @@
 
     BOOST_TEST(!fs::exists(s));
     BOOST_TEST_EQ(s.type(), fs::file_not_found);
- BOOST_TEST(fs::status_known(s));
+ BOOST_TEST(fs::type_present(s));
     BOOST_TEST(!fs::is_regular_file(s));
     BOOST_TEST(!fs::is_directory(s));
     BOOST_TEST(!fs::is_symlink(s));
@@ -1529,12 +1574,17 @@
     // Windows only tests
     if (platform == "Windows")
     {
- cout << "Window specific tests..."
- "\n (may take several seconds)" << endl;
+ cout << "Window specific tests..." << endl;
+ if (!skip_long_windows_tests)
+ {
+ cout << " (may take several seconds)"<< endl;
+
+ BOOST_TEST(!fs::exists(fs::path("//share-not")));
+ BOOST_TEST(!fs::exists(fs::path("//share-not/")));
+ BOOST_TEST(!fs::exists(fs::path("//share-not/foo")));
+ }
+ cout << endl;
 
- BOOST_TEST(!fs::exists(fs::path("//share-not")));
- BOOST_TEST(!fs::exists(fs::path("//share-not/")));
- BOOST_TEST(!fs::exists(fs::path("//share-not/foo")));
       BOOST_TEST(!fs::exists("tools/jam/src/:sys:stat.h")); // !exists() if ERROR_INVALID_NAME
       BOOST_TEST(!fs::exists(":sys:stat.h")); // !exists() if ERROR_INVALID_PARAMETER
       BOOST_TEST(dir.string().size() > 1
@@ -1814,7 +1864,6 @@
 
 int cpp_main(int argc, char* argv[])
 {
-
 // document state of critical macros
 #ifdef BOOST_POSIX_API
   cout << "BOOST_POSIX_API is defined\n";
@@ -1823,8 +1872,15 @@
   cout << "BOOST_WINDOWS_API is defined\n";
 #endif
 
- if (argc > 1 && *argv[1]=='-' && *(argv[1]+1)=='t') report_throws = true;
- if (argc > 1 && *argv[1]=='-' && *(argv[1]+1)=='x') cleanup = false;
+ for (; argc > 1; --argc, ++argv)
+ {
+ if (*argv[1]=='-' && *(argv[1]+1)=='t')
+ report_throws = true;
+ else if (*argv[1]=='-' && *(argv[1]+1)=='x')
+ cleanup = false;
+ else if (*argv[1]=='-' && *(argv[1]+1)=='w')
+ skip_long_windows_tests = true;
+ }
 
   // The choice of platform to test is make at runtime rather than compile-time
   // so that compile errors for all platforms will be detected even though
@@ -1859,6 +1915,7 @@
   initial_tests();
   predicate_and_status_tests();
   exception_tests();
+ platform_specific_tests();
   create_directory_tests();
   current_directory_tests();
   space_tests();
@@ -1894,6 +1951,7 @@
   resize_file_tests();
   absolute_tests();
   canonical_basic_tests();
+ permissions_tests();
   copy_file_tests(f1, d1);
   if (create_symlink_ok) // only if symlinks supported
   {
@@ -1912,7 +1970,6 @@
   write_time_tests(dir);
   
   temp_directory_path_tests();
- platform_specific_tests();
   
   cout << "testing complete" << endl;
 

Modified: trunk/libs/filesystem/v3/test/operations_unit_test.cpp
==============================================================================
--- trunk/libs/filesystem/v3/test/operations_unit_test.cpp (original)
+++ trunk/libs/filesystem/v3/test/operations_unit_test.cpp 2011-10-15 12:02:20 EDT (Sat, 15 Oct 2011)
@@ -40,6 +40,7 @@
 using namespace boost::filesystem;
 using namespace boost::system;
 using std::cout;
+using std::endl;
 using std::string;
 
 #define CHECK(x) check(x, __FILE__, __LINE__)
@@ -53,21 +54,40 @@
 
     ++::boost::detail::test_errors();
 
- std::cout << file << '(' << line << "): test failed\n";
+ cout << file << '(' << line << "): test failed\n";
+ }
+
+ // file_status_test ----------------------------------------------------------------//
+
+ void file_status_test()
+ {
+ cout << "file_status test..." << endl;
+
+ file_status s = status(".");
+ int v = s.permissions();
+ cout << " status(\".\") permissions are "
+ << std::oct << (v & 0777) << std::dec << endl;
+ CHECK((v & 0400) == 0400);
+
+ s = symlink_status(".");
+ v = s.permissions();
+ cout << " symlink_status(\".\") permissions are "
+ << std::oct << (v & 0777) << std::dec << endl;
+ CHECK((v & 0400) == 0400);
   }
 
   // query_test ----------------------------------------------------------------------//
 
   void query_test()
   {
- std::cout << "query test..." << std::endl;
+ cout << "query test..." << endl;
 
     error_code ec;
 
     CHECK(file_size("no-such-file", ec) == static_cast<boost::uintmax_t>(-1));
     CHECK(ec == errc::no_such_file_or_directory);
 
- CHECK(status("no-such-file") == file_status(file_not_found));
+ CHECK(status("no-such-file") == file_status(file_not_found, no_perms));
 
     CHECK(exists("/"));
     CHECK(is_directory("/"));
@@ -76,8 +96,8 @@
     exists("/", ec);
     if (ec)
     {
- std::cout << "exists(\"/\", ec) resulted in non-zero ec.value()" << std::endl;
- std::cout << "ec value: " << ec.value() << ", message: "<< ec.message() << std::endl;
+ cout << "exists(\"/\", ec) resulted in non-zero ec.value()" << endl;
+ cout << "ec value: " << ec.value() << ", message: "<< ec.message() << endl;
     }
     CHECK(!ec);
 
@@ -92,7 +112,7 @@
 
   void directory_iterator_test()
   {
- std::cout << "directory_iterator_test..." << std::endl;
+ cout << "directory_iterator_test..." << endl;
 
     directory_iterator end;
 
@@ -123,14 +143,14 @@
 // cout << " " << it->path().string() << "\n";
     }
 
- std::cout << "directory_iterator_test complete" << std::endl;
+ cout << "directory_iterator_test complete" << endl;
   }
 
   // operations_test -------------------------------------------------------//
 
   void operations_test()
   {
- std::cout << "operations test..." << std::endl;
+ cout << "operations test..." << endl;
 
     error_code ec;
 
@@ -155,13 +175,14 @@
 
   void directory_entry_test()
   {
- std::cout << "directory_entry test..." << std::endl;
+ cout << "directory_entry test..." << endl;
 
- directory_entry de("foo.bar", file_status(regular_file), file_status(directory_file));
+ directory_entry de("foo.bar",
+ file_status(regular_file, owner_all), file_status(directory_file, group_all));
 
     CHECK(de.path() == "foo.bar");
- CHECK(de.status() == file_status(regular_file));
- CHECK(de.symlink_status() == file_status(directory_file));
+ CHECK(de.status() == file_status(regular_file, owner_all));
+ CHECK(de.symlink_status() == file_status(directory_file, group_all));
     CHECK(de < directory_entry("goo.bar"));
     CHECK(de == directory_entry("foo.bar"));
     CHECK(de != directory_entry("goo.bar"));
@@ -173,7 +194,7 @@
 
   void directory_entry_overload_test()
   {
- std::cout << "directory_entry overload test..." << std::endl;
+ cout << "directory_entry overload test..." << endl;
 
     directory_iterator it(".");
     path p(*it);
@@ -183,7 +204,7 @@
 
   void error_handling_test()
   {
- std::cout << "error handling test..." << std::endl;
+ cout << "error handling test..." << endl;
 
     bool threw(false);
     try
@@ -198,7 +219,7 @@
     }
     catch (...)
     {
- cout << "\nunexpected exception type caught" << std::endl;
+ cout << "\nunexpected exception type caught" << endl;
     }
 
     CHECK(threw);
@@ -227,8 +248,9 @@
   cout << "BOOST_FILESYSTEM_DECL" << BOOST_STRINGIZE(=BOOST_FILESYSTEM_DECL) << "\n";
   cout << "BOOST_SYMBOL_VISIBLE" << BOOST_STRINGIZE(=BOOST_SYMBOL_VISIBLE) << "\n";
   
- cout << "current_path() is " << current_path().string() << std::endl;
+ cout << "current_path() is " << current_path().string() << endl;
 
+ file_status_test();
   query_test();
   directory_iterator_test();
   operations_test();
@@ -236,8 +258,8 @@
   directory_entry_overload_test();
   error_handling_test();
 
- std::cout << unique_path() << std::endl;
- std::cout << unique_path("foo-%%%%%-%%%%%-bar") << std::endl;
+ cout << unique_path() << endl;
+ cout << unique_path("foo-%%%%%-%%%%%-bar") << endl;
   
   return ::boost::report_errors();
 }

Modified: trunk/libs/filesystem/v3/test/path_test.cpp
==============================================================================
--- trunk/libs/filesystem/v3/test/path_test.cpp (original)
+++ trunk/libs/filesystem/v3/test/path_test.cpp 2011-10-15 12:02:20 EDT (Sat, 15 Oct 2011)
@@ -1603,7 +1603,7 @@
     BOOST_TEST(!fs::portable_file_name(std::string("foo.")));
   }
   
- // replace_extension_tests ---------------------------------------------------//
+ // replace_extension_tests ---------------------------------------------------------//
 
   void replace_extension_tests()
   {


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