Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r66028 - in trunk: boost/filesystem/v3 libs/filesystem/v3/doc libs/filesystem/v3/src libs/filesystem/v3/test
From: bdawes_at_[hidden]
Date: 2010-10-16 17:03:45


Author: bemandawes
Date: 2010-10-16 17:03:43 EDT (Sat, 16 Oct 2010)
New Revision: 66028
URL: http://svn.boost.org/trac/boost/changeset/66028

Log:
Add temp_directory_path function, contributed by Jeff Flinn. Many thanks to Jeff for the complete implementation, with tests and documentation!
Text files modified:
   trunk/boost/filesystem/v3/operations.hpp | 9 +
   trunk/libs/filesystem/v3/doc/reference.html | 24 ++++
   trunk/libs/filesystem/v3/src/operations.cpp | 50 +++++++++
   trunk/libs/filesystem/v3/test/operations_test.cpp | 215 +++++++++++++++++++++++++++++++++++++++
   4 files changed, 294 insertions(+), 4 deletions(-)

Modified: trunk/boost/filesystem/v3/operations.hpp
==============================================================================
--- trunk/boost/filesystem/v3/operations.hpp (original)
+++ trunk/boost/filesystem/v3/operations.hpp 2010-10-16 17:03:43 EDT (Sat, 16 Oct 2010)
@@ -191,6 +191,8 @@
     BOOST_FILESYSTEM_DECL
     path system_complete(const path& p, system::error_code* ec=0);
     BOOST_FILESYSTEM_DECL
+ path temp_directory_path(system::error_code* ec=0);
+ BOOST_FILESYSTEM_DECL
     path unique_path(const path& p, system::error_code* ec=0);
   } // namespace detail
 
@@ -446,6 +448,12 @@
   path system_complete(const path& p, system::error_code& ec)
                                        {return detail::system_complete(p, &ec);}
   inline
+ path temp_directory_path() {return detail::temp_directory_path();}
+
+ inline
+ path temp_directory_path(system::error_code& ec)
+ {return detail::temp_directory_path(&ec);}
+ inline
   path unique_path(const path& p="%%%%-%%%%-%%%%-%%%%")
                                        { return detail::unique_path(p); }
   inline
@@ -986,6 +994,7 @@
     using filesystem3::symlink_file;
     using filesystem3::symlink_status;
     using filesystem3::system_complete;
+ using filesystem3::temp_directory_path;
     using filesystem3::type_unknown;
     using filesystem3::unique_path;
 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED

Modified: trunk/libs/filesystem/v3/doc/reference.html
==============================================================================
--- trunk/libs/filesystem/v3/doc/reference.html (original)
+++ trunk/libs/filesystem/v3/doc/reference.html 2010-10-16 17:03:43 EDT (Sat, 16 Oct 2010)
@@ -114,6 +114,7 @@
 &nbsp;&nbsp;&nbsp;&nbsp status_known<br>
 &nbsp;&nbsp;&nbsp;&nbsp symlink_status<br>
 &nbsp;&nbsp;&nbsp;&nbsp system_complete<br>
+&nbsp;&nbsp;&nbsp;&nbsp temp_directory_path<br>
 &nbsp;&nbsp;&nbsp;&nbsp; unique_path</td>
     <td width="34%" valign="top">
     <a href="#File-streams">File streams</a><br>
@@ -437,6 +438,9 @@
       path system_complete(const path&amp; p);
       path system_complete(const path&amp; p, system::error_code&amp; ec);
 
+ path temp_directory_path();
+ path temp_directory_path(system::error_code&amp; ec);
+
       path unique_path(const path&amp; model=&quot;%%%%-%%%%-%%%%-%%%%&quot;);
       path unique_path(const path&amp; model, system::error_code&amp; ec);
 
@@ -2442,6 +2446,21 @@
   <p>See <a href="#complete_note">
   <i>complete()</i> note</a> for usage suggestions. <i>-- end note</i>]</p>
 </blockquote>
+<pre>path <a name="temp_directory_path">temp_directory_path</a>();
+path temp_directory_path(system::error_code&amp; ec);</pre>
+<blockquote>
+ <p><i>Returns:</i> A directory path suitable for temporary files under the
+ conventions of the operating system. The specifics of how this path is
+ determined are implementation defined. An error shall be reported if<code> !exists(p)
+ || !is_directory(p)</code>, where <code>p</code> is the path to be returned.</p>
+ <p><i>POSIX:</i> The path supplied by the first environment variable in the
+ list TMPDIR, TMP, TEMP, TEMPDIR that names an existing directory.</p>
+ <p><i>Windows:</i> The path reported by the <i>Windows</i> <code>GetTempPath</code> API function.</p>
+ <p><i>Throws:</i> As specified in <a href="#Error-reporting">
+ Error reporting</a>.</p>
+ <p>[<i>Note: </i>The <code>temp_directory_path()</code> name was chosen to emphasize that the return is a
+ path, not just a single directory name.&nbsp; <i>-- end note</i>]</p>
+</blockquote>
 <pre>path <a name="unique_path">unique_path</a>(const path&amp; model=&quot;%%%%-%%%%-%%%%-%%%%&quot;);
 path unique_path(const path&amp; model, system::error_code&amp; ec);</pre>
 <blockquote>
@@ -3038,7 +3057,8 @@
 <p>Dietmar Kuehl contributed the original Boost Filesystem Library directory_iterator design. Peter Dimov, Walter Landry, Rob Stewart, and Thomas
 Witt were particularly helpful in refining the library.</p>
 <p>The create_directories, extension, basename, and replace_extension functions
-were developed by Vladimir Prus.</p>
+were developed by Vladimir Prus. The temp_directory_path function was
+contributed by Jeff Flinn.</p>
 <p>Howard Hinnant and John Maddock reviewed a draft of the version 2 proposal, and
 identified a number of mistakes or weaknesses, resulting in a more polished
 final document.</p>
@@ -3069,7 +3089,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 -->05 October 2010<!--webbot bot="Timestamp" endspan i-checksum="32123" --></p>
+<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->16 October 2010<!--webbot bot="Timestamp" endspan i-checksum="32126" --></p>
 
 </body>
 

Modified: trunk/libs/filesystem/v3/src/operations.cpp
==============================================================================
--- trunk/libs/filesystem/v3/src/operations.cpp (original)
+++ trunk/libs/filesystem/v3/src/operations.cpp 2010-10-16 17:03:43 EDT (Sat, 16 Oct 2010)
@@ -49,6 +49,7 @@
 #include <boost/scoped_array.hpp>
 #include <boost/detail/workaround.hpp>
 #include <cstdlib> // for malloc, free
+#include <vector>
 
 #ifdef BOOST_FILEYSTEM_INCLUDE_IOSTREAM
 # include <iostream>
@@ -1512,6 +1513,55 @@
 # endif
   }
 
+ // contributed by Jeff Flinn
+ BOOST_FILESYSTEM_DECL
+ path temp_directory_path(system::error_code* ec)
+ {
+# ifdef BOOST_POSIX_API
+ const char* val = 0;
+
+ (val = std::getenv("TMPDIR" )) ||
+ (val = std::getenv("TMP" )) ||
+ (val = std::getenv("TEMP" )) ||
+ (val = std::getenv("TEMPDIR"));
+
+ path p((val!=0)? val : "");
+
+ if(!val||(ec&&!is_directory(p, *ec))||(!ec&&!is_directory(p)))
+ {
+ errno = ENOTDIR;
+ error(true, ec, "boost::filesystem::temp_directory_path");
+ return p;
+ }
+
+ return p;
+
+# else // Windows
+
+ std::vector<path::value_type> buf(GetTempPathW(0, NULL));
+
+ if(buf.empty() || GetTempPathW(buf.size(), &buf[0])==0)
+ {
+ if(!buf.empty()) ::SetLastError(ENOTDIR);
+ error(true, ec, "boost::filesystem::temp_directory_path");
+ return path();
+ }
+
+ buf.pop_back();
+
+ path p(buf.begin(), buf.end());
+
+ if((ec&&!is_directory(p, *ec))||(!ec&&!is_directory(p)))
+ {
+ ::SetLastError(ENOTDIR);
+ error(true, ec, "boost::filesystem::temp_directory_path");
+ return path();
+ }
+
+ return p;
+# endif
+ }
+
   BOOST_FILESYSTEM_DECL
   path system_complete(const path& p, system::error_code* ec)
   {

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 2010-10-16 17:03:43 EDT (Sat, 16 Oct 2010)
@@ -46,12 +46,35 @@
 
 #ifdef BOOST_WINDOWS_API
 # include <windows.h>
+
+inline std::wstring convert(const char* c)
+{
+ std::string s(c);
+
+ return std::wstring(s.begin(), s.end());
+}
+
+inline int setenv(const char* name, const fs::path::value_type* val, int)
+{
+ return SetEnvironmentVariableW(convert(name).c_str(), val);
+}
+
+inline int setenv(const char* name, const char* val, int)
+{
+ return SetEnvironmentVariableW(convert(name).c_str(), convert(val).c_str());
+}
+
+inline int unsetenv(const char* name)
+{
+ return SetEnvironmentVariableW(convert(name).c_str(), 0);
+}
+
 #endif
 
 // on Windows, except for standard libaries known to have wchar_t overloads for
 // file stream I/O, use path::string() to get a narrow character c_str()
 #if defined(BOOST_WINDOWS_API) \
- && !(defined(_CPPLIB_VER) && _CPPLIB_VER >= 405) // not (Dinkumware with overloads)
+ && (!defined(_CPPLIB_VER) || _CPPLIB_VER < 405) // not Dinkumware || no wide overloads
 # define BOOST_FILESYSTEM_C_STR string().c_str() // use narrow, since wide not available
 #else // use the native c_str, which will be narrow on POSIX, wide on Windows
 # define BOOST_FILESYSTEM_C_STR c_str()
@@ -1413,6 +1436,192 @@
     BOOST_TEST(!fs::equivalent(ng, f1));
   }
 
+ // temp_directory_path_tests -------------------------------------------------------//
+ // contributed by Jeff Flinn
+
+ struct guarded_env_var
+ {
+ struct previous_value
+ {
+ std::string m_name;
+ std::string m_string;
+ bool m_empty;
+
+ previous_value(const char* name)
+ : m_string(name)
+ , m_empty (true)
+ {
+ if(const char* value = getenv(name))
+ {
+ m_string.assign(value);
+ m_empty = false;
+ }
+ else
+ {
+ m_empty = true;
+ }
+ }
+ ~previous_value()
+ {
+ m_empty? unsetenv(m_name.c_str())
+ : setenv(m_name.c_str(), m_string.c_str(), 1);
+ }
+ };
+
+ previous_value m_previous_value;
+
+ guarded_env_var(const char* name, const fs::path::value_type* value)
+ : m_previous_value(name)
+ {
+ value? setenv(name, value, 1) : unsetenv(name);
+ }
+ };
+
+ void temp_directory_path_tests()
+ {
+ {
+ std::cout << "temp_directory_path_tests..." << std::endl;
+
+ BOOST_TEST(!fs::temp_directory_path().empty());
+ BOOST_TEST(exists(fs::temp_directory_path()));
+ fs::path ph = fs::temp_directory_path()/"temp_directory_path_test.txt";
+ {
+ if(exists(ph)) remove(ph);
+ std::ofstream f(ph.BOOST_FILESYSTEM_C_STR);
+ f << "passed";
+ }
+ BOOST_TEST(exists(ph));
+ {
+ std::ifstream f(ph.BOOST_FILESYSTEM_C_STR);
+ std::string s;
+ f >> s;
+ BOOST_TEST(s == "passed");
+ }
+ remove(ph);
+ BOOST_TEST(!exists(ph));
+ }
+
+ fs::path test_temp_dir = init_path;
+
+#if defined BOOST_POSIX_API
+ {
+ struct guarded_tmp_vars
+ {
+ guarded_env_var m_tmpdir ;
+ guarded_env_var m_tmp ;
+ guarded_env_var m_temp ;
+ guarded_env_var m_tempdir;
+
+ guarded_tmp_vars
+ ( const fs::path::value_type* tmpdir
+ , const fs::path::value_type* tmp
+ , const fs::path::value_type* temp
+ , const fs::path::value_type* tempdir
+ )
+ : m_tmpdir ("TMPDIR" , tmpdir )
+ , m_tmp ("TMP" , tmp )
+ , m_temp ("TEMP" , temp )
+ , m_tempdir("TEMPDIR", tempdir)
+ {}
+ };
+
+ try
+ {
+ guarded_tmp_vars vars(0, 0, 0, 0);
+ fs::path ph = fs::temp_directory_path();
+
+ BOOST_TEST(false); // should throw
+ }
+ catch(const boost::filesystem::filesystem_error& e)
+ {
+ BOOST_TEST(e.code() == boost::system::errc::not_a_directory);
+ }
+
+ {
+ guarded_tmp_vars vars(0, 0, 0, 0);
+ error_code ec;
+ fs::path ph = fs::temp_directory_path(ec);
+ BOOST_TEST(ec);
+ BOOST_TEST(ec == boost::system::errc::not_a_directory);
+ }
+
+ {
+ guarded_tmp_vars vars(test_temp_dir.BOOST_FILESYSTEM_C_STR, 0, 0, 0);
+ fs::path ph = fs::temp_directory_path();
+ BOOST_TEST(equivalent(test_temp_dir, ph));
+ }
+ {
+ guarded_tmp_vars vars(0, test_temp_dir.BOOST_FILESYSTEM_C_STR, 0, 0);
+ fs::path ph = fs::temp_directory_path();
+ BOOST_TEST(equivalent(test_temp_dir, ph));
+ }
+ {
+ guarded_tmp_vars vars(0, 0, test_temp_dir.BOOST_FILESYSTEM_C_STR, 0);
+ fs::path ph = fs::temp_directory_path();
+ BOOST_TEST(equivalent(test_temp_dir, ph));
+ }
+ {
+ guarded_tmp_vars vars(0, 0, 0, test_temp_dir.BOOST_FILESYSTEM_C_STR);
+ fs::path ph = fs::temp_directory_path();
+ BOOST_TEST(equivalent(test_temp_dir, ph));
+ }
+ }
+#endif
+
+#if defined BOOST_WINDOWS_API
+ {
+ struct guarded_tmp_vars
+ {
+ guarded_env_var m_tmp ;
+ guarded_env_var m_temp ;
+ guarded_env_var m_userprofile;
+
+ guarded_tmp_vars
+ ( const fs::path::value_type* tmp
+ , const fs::path::value_type* temp
+ , const fs::path::value_type* userprofile
+ )
+ : m_tmp ("TMP" , tmp )
+ , m_temp ("TEMP" , temp )
+ , m_userprofile("USERPROFILE", userprofile)
+ {}
+ };
+
+ // should NEVER throw - the windows directory or current_path always exists
+ {
+ guarded_tmp_vars vars(0, 0, 0);
+ fs::path ph = fs::temp_directory_path();
+
+ BOOST_TEST(test_temp_dir != ph);
+ }
+
+ // should NEVER fail - the windows directory or current_path always exists
+ {
+ guarded_tmp_vars vars(0, 0, 0);
+ error_code ec;
+ fs::path ph = fs::temp_directory_path(ec);
+ BOOST_TEST(!ec);
+ }
+
+ {
+ guarded_tmp_vars vars(test_temp_dir.c_str(), 0, 0);
+ fs::path ph = fs::temp_directory_path();
+ BOOST_TEST(equivalent(test_temp_dir, ph));
+ }
+ {
+ guarded_tmp_vars vars(0, test_temp_dir.c_str(), 0);
+ fs::path ph = fs::temp_directory_path();
+ BOOST_TEST(equivalent(test_temp_dir, ph));
+ }
+ {
+ guarded_tmp_vars vars(0, 0, test_temp_dir.c_str());
+ fs::path ph = fs::temp_directory_path();
+ BOOST_TEST(equivalent(test_temp_dir, ph));
+ }
+ }
+#endif
+ }
+
   // _tests --------------------------------------------------------------------------//
 
   void _tests()
@@ -1520,7 +1729,9 @@
   if (create_symlink_ok) // only if symlinks supported
     remove_symlink_tests();
   write_time_tests(dir);
-
+
+ temp_directory_path_tests();
+
   std::cout << "testing complete" << std::endl;
 
   // post-test cleanup


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