libstdc++: Use secure_getenv for filesystem::temp_directory_path() [PR65018]

This adds a configure check for the GNU extension secure_getenv and then
uses it for looking up TMPDIR and similar variables.

Signed-off-by: Jonathan Wakely <jwakely@redhat.com>

libstdc++-v3/ChangeLog:

	PR libstdc++/65018
	* configure.ac: Check for secure_getenv.
	* config.h.in: Regenerate.
	* configure: Regenerate.
	* src/filesystem/ops-common.h (get_temp_directory_from_env): New
	helper function to obtain path from the environment.
	* src/c++17/fs_ops.cc (fs::temp_directory_path): Use new helper.
	* src/filesystem/ops.cc (fs::temp_directory_path): Likewise.
	* testsuite/27_io/filesystem/operations/temp_directory_path.cc:
	Print messages if test cannot be run.
	* testsuite/experimental/filesystem/operations/temp_directory_path.cc:
	Likewise. Fix incorrect condition. Use "TMP" to work with
	Windows as well as POSIX.
This commit is contained in:
Jonathan Wakely 2021-07-30 13:56:14 +01:00
parent 2065654435
commit 3dbd4d94bf
8 changed files with 80 additions and 54 deletions

View File

@ -301,6 +301,9 @@
/* Define if readlink is available in <unistd.h>. */
#undef HAVE_READLINK
/* Define to 1 if you have the `secure_getenv' function. */
#undef HAVE_SECURE_GETENV
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV

View File

@ -28225,6 +28225,17 @@ if test "x$ac_cv_func__wfopen" = xyes; then :
#define HAVE__WFOPEN 1
_ACEOF
fi
done
for ac_func in secure_getenv
do :
ac_fn_c_check_func "$LINENO" "secure_getenv" "ac_cv_func_secure_getenv"
if test "x$ac_cv_func_secure_getenv" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SECURE_GETENV 1
_ACEOF
fi
done

View File

@ -273,6 +273,7 @@ if $GLIBCXX_IS_NATIVE; then
AC_CHECK_FUNCS(__cxa_thread_atexit_impl __cxa_thread_atexit)
AC_CHECK_FUNCS(aligned_alloc posix_memalign memalign _aligned_malloc)
AC_CHECK_FUNCS(_wfopen)
AC_CHECK_FUNCS(secure_getenv)
# C11 functions for C++17 library
AC_CHECK_FUNCS(timespec_get)

View File

@ -1591,7 +1591,8 @@ fs::symlink_status(const fs::path& p)
return result;
}
fs::path fs::temp_directory_path()
fs::path
fs::temp_directory_path()
{
error_code ec;
path tmp = temp_directory_path(ec);
@ -1600,32 +1601,10 @@ fs::path fs::temp_directory_path()
return tmp;
}
fs::path fs::temp_directory_path(error_code& ec)
fs::path
fs::temp_directory_path(error_code& ec)
{
path p;
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
unsigned len = 1024;
std::wstring buf;
do
{
buf.resize(len);
len = GetTempPathW(buf.size(), buf.data());
} while (len > buf.size());
if (len == 0)
{
ec.assign((int)GetLastError(), std::system_category());
return p;
}
buf.resize(len);
p = std::move(buf);
#else
const char* tmpdir = nullptr;
const char* env[] = { "TMPDIR", "TMP", "TEMP", "TEMPDIR", nullptr };
for (auto e = env; tmpdir == nullptr && *e != nullptr; ++e)
tmpdir = ::getenv(*e);
p = tmpdir ? tmpdir : "/tmp";
#endif
path p = fs::get_temp_directory_from_env();
auto st = status(p, ec);
if (ec)
p.clear();

View File

@ -568,6 +568,46 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
#endif // _GLIBCXX_HAVE_SYS_STAT_H
// Find OS-specific name of temporary directory from the environment,
// Caller must check that the path is an accessible directory.
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
inline wstring
get_temp_directory_from_env()
{
unsigned len = 1024;
std::wstring buf;
do
{
buf.resize(len);
len = GetTempPathW(buf.size(), buf.data());
} while (len > buf.size());
if (len == 0)
{
ec.assign((int)GetLastError(), std::system_category());
return p;
}
buf.resize(len);
return buf;
}
#else
inline const char*
get_temp_directory_from_env() noexcept
{
for (auto env : { "TMPDIR", "TMP", "TEMP", "TEMPDIR" })
{
#if _GLIBCXX_HAVE_SECURE_GETENV
auto tmpdir = ::secure_getenv(env);
#else
auto tmpdir = ::getenv(env);
#endif
if (tmpdir)
return tmpdir;
}
return "/tmp";
}
#endif
_GLIBCXX_END_NAMESPACE_FILESYSTEM
_GLIBCXX_END_NAMESPACE_VERSION

View File

@ -1289,7 +1289,8 @@ fs::system_complete(const path& p, error_code& ec)
#endif
}
fs::path fs::temp_directory_path()
fs::path
fs::temp_directory_path()
{
error_code ec;
path tmp = temp_directory_path(ec);
@ -1298,31 +1299,10 @@ fs::path fs::temp_directory_path()
return tmp;
}
fs::path fs::temp_directory_path(error_code& ec)
fs::path
fs::temp_directory_path(error_code& ec)
{
path p;
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
unsigned len = 1024;
std::wstring buf;
do
{
buf.resize(len);
len = GetTempPathW(buf.size(), buf.data());
} while (len > buf.size());
if (len == 0)
{
ec.assign((int)GetLastError(), std::system_category());
return p;
}
buf.resize(len);
p = std::move(buf);
#else
const char* tmpdir = nullptr;
const char* env[] = { "TMPDIR", "TMP", "TEMP", "TEMPDIR", nullptr };
for (auto e = env; tmpdir == nullptr && *e != nullptr; ++e)
tmpdir = ::getenv(*e);
p = tmpdir ? tmpdir : "/tmp";
path p = fs::get_temp_directory_from_env();
auto st = status(p, ec);
if (ec)
p.clear();
@ -1331,7 +1311,5 @@ fs::path fs::temp_directory_path(error_code& ec)
p.clear();
ec = std::make_error_code(std::errc::not_a_directory);
}
#endif
return p;
}

View File

@ -20,6 +20,7 @@
#include <filesystem>
#include <stdlib.h>
#include <stdio.h>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
@ -58,7 +59,10 @@ test01()
clean_env();
if (!fs::exists("/tmp"))
{
puts("/tmp doesn't exist, not testing it for temp_directory_path");
return; // just give up
}
std::error_code ec = make_error_code(std::errc::invalid_argument);
fs::path p1 = fs::temp_directory_path(ec);
@ -75,7 +79,10 @@ test02()
clean_env();
if (!set_env("TMP", __gnu_test::nonexistent_path().string()))
{
puts("Cannot set environment variables, not testing temp_directory_path");
return; // just give up
}
std::error_code ec;
fs::path p = fs::temp_directory_path(ec);

View File

@ -21,6 +21,7 @@
#include <experimental/filesystem>
#include <stdlib.h>
#include <stdio.h>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
@ -59,7 +60,10 @@ test01()
clean_env();
if (!fs::exists("/tmp"))
{
puts("/tmp doesn't exist, not testing it for temp_directory_path");
return; // just give up
}
std::error_code ec = make_error_code(std::errc::invalid_argument);
fs::path p1 = fs::temp_directory_path(ec);
@ -75,8 +79,11 @@ test02()
{
clean_env();
if (set_env("TMPDIR", __gnu_test::nonexistent_path().string()))
if (!set_env("TMP", __gnu_test::nonexistent_path().string()))
{
puts("Cannot set environment variables, not testing temp_directory_path");
return; // just give up
}
std::error_code ec;
fs::path p = fs::temp_directory_path(ec);