Ticket #4724: temp_dir_path3.patch

File temp_dir_path3.patch, 12.1 KB (added by Jeff Flinn <jflinn@…>, 12 years ago)

replace previous patches, on error set ENOTDIR, add tests for env existence

  • boost/filesystem/v3/operations.hpp

     
    188188    BOOST_FILESYSTEM_DECL
    189189    path system_complete(const path& p, system::error_code* ec=0);
    190190    BOOST_FILESYSTEM_DECL
     191    path temp_dir_path(system::error_code* ec=0);
     192    BOOST_FILESYSTEM_DECL
    191193    path unique_path(const path& p, system::error_code* ec=0);
    192194  }  // namespace detail
    193195
     
    443445  path system_complete(const path& p, system::error_code& ec)
    444446                                       {return detail::system_complete(p, &ec);}
    445447  inline
     448  path temp_dir_path()                {return detail::temp_dir_path();}
     449
     450  inline
     451  path temp_dir_path(system::error_code& ec)
     452                                       {return detail::temp_dir_path(&ec);}
     453  inline
    446454  path unique_path(const path& p="%%%%-%%%%-%%%%-%%%%")
    447455                                       { return detail::unique_path(p); }
    448456  inline
     
    982990    using filesystem3::symlink_file;
    983991    using filesystem3::symlink_status;
    984992    using filesystem3::system_complete;
     993    using filesystem3::temp_dir_path;
    985994    using filesystem3::type_unknown;
    986995    using filesystem3::unique_path;
    987996# ifndef BOOST_FILESYSTEM_NO_DEPRECATED
  • libs/filesystem/v3/test/operations_test.cpp

     
    4545
    4646#ifdef BOOST_WINDOWS_API
    4747# include <windows.h>
     48
     49inline std::wstring convert(const char* c)
     50{
     51   std::string s(c);
     52   
     53   return std::wstring(s.begin(), s.end());
     54}
     55
     56inline int setenv(const char* name, const fs::path::value_type* val, int)
     57{
     58  return SetEnvironmentVariableW(convert(name).c_str(), val);
     59}
     60
     61inline int setenv(const char* name, const char* val, int)
     62{
     63  return SetEnvironmentVariableW(convert(name).c_str(), convert(val).c_str());
     64}
     65
     66inline int unsetenv(const char* name)
     67{
     68  return SetEnvironmentVariableW(convert(name).c_str(), 0);
     69}
     70
    4871#endif
    4972
    5073//  on Windows, except for standard libaries known to have wchar_t overloads for
     
    12691292    BOOST_TEST(!fs::equivalent(ng, file_ph));
    12701293  }
    12711294
     1295  //  temp_dir_path_tests  ---------------------------------------------------------//
     1296 
     1297  struct guarded_env_var
     1298  {
     1299    struct previous_value
     1300    {
     1301      std::string m_name;
     1302      std::string m_string;
     1303      bool        m_empty;
     1304     
     1305      previous_value(const char* name)
     1306      : m_string(name)
     1307      , m_empty (true)
     1308      {
     1309        if(const char* value = getenv(name))
     1310        {
     1311          m_string.assign(value);
     1312          m_empty = false;
     1313        }
     1314        else
     1315        {
     1316          m_empty = true;
     1317        }
     1318      }
     1319      ~previous_value()
     1320      {
     1321        m_empty? unsetenv(m_name.c_str())
     1322               : setenv(m_name.c_str(), m_string.c_str(), 1);
     1323      }
     1324    };
     1325 
     1326    previous_value m_previous_value;
     1327   
     1328    guarded_env_var(const char* name, const fs::path::value_type* value)
     1329    : m_previous_value(name)
     1330    {
     1331      value? setenv(name, value, 1) : unsetenv(name);
     1332    }
     1333  };
     1334
     1335  void temp_dir_path_tests()
     1336  {
     1337    {
     1338      std::cout << "temp_dir_path_tests..." << std::endl;
     1339
     1340      BOOST_TEST(!fs::temp_dir_path().empty());
     1341      BOOST_TEST(exists(fs::temp_dir_path()));
     1342      fs::path ph = fs::temp_dir_path()/"temp_dir_path_test.txt";
     1343      {
     1344          if(exists(ph)) remove(ph);
     1345          std::ofstream f(ph.BOOST_FILESYSTEM_C_STR);
     1346          f << "passed";
     1347      }
     1348      BOOST_TEST(exists(ph));
     1349      {
     1350          std::ifstream f(ph.BOOST_FILESYSTEM_C_STR);
     1351          std::string   s;
     1352          f >> s;
     1353          BOOST_TEST(s == "passed");
     1354      }
     1355      remove(ph);
     1356      BOOST_TEST(!exists(ph));
     1357    }
     1358   
     1359    fs::path test_temp_dir = init_path;
     1360
     1361#if defined BOOST_POSIX_API
     1362    {
     1363      struct guarded_tmp_vars
     1364      {
     1365        guarded_env_var m_tmpdir ;
     1366        guarded_env_var m_tmp    ;
     1367        guarded_env_var m_temp   ;
     1368        guarded_env_var m_tempdir;
     1369
     1370        guarded_tmp_vars
     1371        ( const fs::path::value_type* tmpdir 
     1372        , const fs::path::value_type* tmp   
     1373        , const fs::path::value_type* temp   
     1374        , const fs::path::value_type* tempdir
     1375        )
     1376        : m_tmpdir ("TMPDIR" , tmpdir )
     1377        , m_tmp    ("TMP"    , tmp    )
     1378        , m_temp   ("TEMP"   , temp   )
     1379        , m_tempdir("TEMPDIR", tempdir)
     1380        {}               
     1381      };
     1382
     1383      try
     1384      {
     1385        guarded_tmp_vars vars(0, 0, 0, 0);
     1386        fs::path ph = fs::temp_dir_path();
     1387       
     1388        BOOST_TEST(false); // should throw
     1389      }
     1390      catch(const boost::filesystem::filesystem_error& e)
     1391      {
     1392        BOOST_TEST(e.code() == boost::system::errc::not_a_directory);
     1393      }
     1394     
     1395      {
     1396          guarded_tmp_vars vars(0, 0, 0, 0);
     1397          error_code ec;
     1398          fs::path ph = fs::temp_dir_path(ec);
     1399          BOOST_TEST(ec);
     1400          BOOST_TEST(ec == boost::system::errc::not_a_directory);
     1401      }
     1402     
     1403      {
     1404        guarded_tmp_vars vars(test_temp_dir.BOOST_FILESYSTEM_C_STR, 0, 0, 0);
     1405        fs::path ph = fs::temp_dir_path();
     1406        BOOST_TEST(equivalent(test_temp_dir, ph));
     1407      }
     1408      {
     1409        guarded_tmp_vars vars(0, test_temp_dir.BOOST_FILESYSTEM_C_STR, 0, 0);
     1410        fs::path ph = fs::temp_dir_path();
     1411        BOOST_TEST(equivalent(test_temp_dir, ph));
     1412      }
     1413      {
     1414        guarded_tmp_vars vars(0, 0, test_temp_dir.BOOST_FILESYSTEM_C_STR, 0);
     1415        fs::path ph = fs::temp_dir_path();
     1416        BOOST_TEST(equivalent(test_temp_dir, ph));
     1417      }
     1418      {
     1419        guarded_tmp_vars vars(0, 0, 0, test_temp_dir.BOOST_FILESYSTEM_C_STR);
     1420        fs::path ph = fs::temp_dir_path();
     1421        BOOST_TEST(equivalent(test_temp_dir, ph));
     1422      }
     1423    }
     1424#endif
     1425
     1426#if defined BOOST_WINDOWS_API
     1427    {
     1428      struct guarded_tmp_vars
     1429      {
     1430        guarded_env_var m_tmp        ;
     1431        guarded_env_var m_temp       ;
     1432        guarded_env_var m_userprofile;
     1433
     1434        guarded_tmp_vars
     1435        ( const fs::path::value_type* tmp   
     1436        , const fs::path::value_type* temp   
     1437        , const fs::path::value_type* userprofile
     1438        )
     1439        : m_tmp        ("TMP"        , tmp        )
     1440        , m_temp       ("TEMP"       , temp       )
     1441        , m_userprofile("USERPROFILE", userprofile)
     1442        {}               
     1443      };
     1444
     1445      // should NEVER throw - the windows directory or current_path always exists
     1446      {
     1447        guarded_tmp_vars vars(0, 0, 0);
     1448        fs::path ph = fs::temp_dir_path();
     1449       
     1450        BOOST_TEST(test_temp_dir != ph);
     1451      }
     1452
     1453      // should NEVER fail - the windows directory or current_path always exists
     1454      {
     1455          guarded_tmp_vars vars(0, 0, 0);
     1456          error_code ec;
     1457          fs::path ph = fs::temp_dir_path(ec);
     1458          BOOST_TEST(!ec);
     1459      }
     1460
     1461      {
     1462        guarded_tmp_vars vars(test_temp_dir.BOOST_FILESYSTEM_C_STR, 0, 0);
     1463        fs::path ph = fs::temp_dir_path();
     1464        BOOST_TEST(equivalent(test_temp_dir, ph));
     1465      }
     1466      {
     1467        guarded_tmp_vars vars(0, test_temp_dir.BOOST_FILESYSTEM_C_STR, 0);
     1468        fs::path ph = fs::temp_dir_path();
     1469        BOOST_TEST(equivalent(test_temp_dir, ph));
     1470      }
     1471      {
     1472        guarded_tmp_vars vars(0, 0, test_temp_dir.BOOST_FILESYSTEM_C_STR);
     1473        fs::path ph = fs::temp_dir_path();
     1474        BOOST_TEST(equivalent(test_temp_dir, ph));
     1475      }
     1476    }
     1477#endif   
     1478  }
     1479
    12721480  //  _tests  --------------------------------------------------------------------------//
    12731481
    12741482  void _tests()
     
    13931601  if (create_symlink_ok)  // only if symlinks supported
    13941602    remove_symlink_tests();
    13951603  write_time_tests(dir);
    1396 
     1604 
     1605  temp_dir_path_tests();
     1606 
    13971607  std::cout << "testing complete" << std::endl;
    13981608
    13991609  // post-test cleanup
  • libs/filesystem/v3/doc/reference.html

     
    114114&nbsp;&nbsp;&nbsp;&nbsp <a href="#status_known">status_known</a><br>
    115115&nbsp;&nbsp;&nbsp;&nbsp <a href="#symlink_status">symlink_status</a><br>
    116116&nbsp;&nbsp;&nbsp;&nbsp <a href="#system_complete">system_complete</a><br>
     117&nbsp;&nbsp;&nbsp;&nbsp <a href="#temp_dir_path">temp_dir_path</a><br>
    117118&nbsp;&nbsp;&nbsp;&nbsp; <a href="#unique_path">unique_path</a></td>
    118119    <td width="34%" valign="top">
    119120    <a href="#File-streams">File streams</a><br>
     
    437438      path         <a href="#system_complete">system_complete</a>(const path&amp; p);
    438439      path         <a href="#system_complete">system_complete</a>(const path&amp; p, system::error_code&amp; ec);
    439440
     441      path         <a href="#temp_dir_path">temp_dir_path</a>();
     442      path         <a href="#temp_dir_path">temp_dir_path</a>(system::error_code&amp; ec);
     443
    440444      path         <a href="#unique_path">unique_path</a>(const path&amp; model=&quot;%%%%-%%%%-%%%%-%%%%&quot;);
    441445      path         <a href="#unique_path">unique_path</a>(const path&amp; model, system::error_code&amp; ec);
    442446
     
    24422446  <p>See <a href="#complete_note">
    24432447  <i>complete()</i> note</a> for usage suggestions. <i>-- end note</i>]</p>
    24442448</blockquote>
     2449<pre>path <a name="temp_dir_path">temp_dir_path</a>();
     2450path temp_dir_path(system::error_code&amp; ec);</pre>
     2451<blockquote>
     2452  <p><i>Returns:</i> The temporary directory path as returned by the <i>POSIX</i> <code>getenv("TMPDIR")</code> environment variable,
     2453  or the <i>Windows</i> <code>GetTempPath</code> API function. <code>is_directory()</code> is true for the returned path.
     2454  </p>
     2455  <p><i>Throws:</i> As specified in <a href="#Error-reporting">
     2456  Error reporting</a>.</p>
     2457  <p>[<i>Note: </i>The <code>temp_dir_path()</code> name was chosen to emphasize that the return is a
     2458  path, not just a single directory name.</p>
     2459  <p>For <i>POSIX</i> systems the definition of the first existing environment variable from the list: TMPDIR, TMP, TEMP, TEMPDIR is used.
     2460  &nbsp; <i>-- end note</i>]</p>
     2461</blockquote>
    24452462<pre>path <a name="unique_path">unique_path</a>(const path&amp; model=&quot;%%%%-%%%%-%%%%-%%%%&quot;);
    24462463path unique_path(const path&amp; model, system::error_code&amp; ec);</pre>
    24472464<blockquote>
  • libs/filesystem/v3/src/operations.cpp

     
    4949#include <boost/scoped_array.hpp>
    5050#include <boost/detail/workaround.hpp>
    5151#include <cstdlib>  // for malloc, free
     52#include <vector>
    5253
    5354#ifdef BOOST_FILEYSTEM_INCLUDE_IOSTREAM
    5455# include <iostream>
     
    14451446  }
    14461447
    14471448  BOOST_FILESYSTEM_DECL
     1449  path temp_dir_path(system::error_code* ec)
     1450  {
     1451#   ifdef BOOST_POSIX_API
     1452      const char* val = 0;
     1453     
     1454      (val = std::getenv("TMPDIR" )) ||
     1455      (val = std::getenv("TMP"    )) ||
     1456      (val = std::getenv("TEMP"   )) ||
     1457      (val = std::getenv("TEMPDIR"));
     1458     
     1459      path p((val!=0)? val : "");
     1460     
     1461      if(!val||(ec&&!is_directory(p, *ec))||(!ec&&!is_directory(p)))
     1462      {
     1463        errno = ENOTDIR;
     1464        error(true, ec, "boost::filesystem::temp_dir_path");
     1465        return p;
     1466      }
     1467       
     1468      return p;
     1469     
     1470#   else  // Windows
     1471
     1472      std::vector<path::value_type> buf(GetTempPathW(0, NULL));
     1473
     1474      if(buf.empty() || GetTempPathW(buf.size(), &buf[0])==0)
     1475      {
     1476        if(!buf.empty()) ::SetLastError(ENOTDIR);
     1477        error(true, ec, "boost::filesystem::temp_dir_path");
     1478        return path();
     1479      }
     1480         
     1481      buf.pop_back();
     1482     
     1483      path p(buf.begin(), buf.end());
     1484         
     1485      if((ec&&!is_directory(p, *ec))||(!ec&&!is_directory(p)))
     1486      {
     1487        ::SetLastError(ENOTDIR);
     1488        error(true, ec, "boost::filesystem::temp_dir_path");
     1489        return path();
     1490      }
     1491     
     1492      return p;
     1493#   endif
     1494  }
     1495 
     1496  BOOST_FILESYSTEM_DECL
    14481497  path system_complete(const path& p, system::error_code* ec)
    14491498  {
    14501499#   ifdef BOOST_POSIX_API