libstdc++: Add autoconf checks for mkdir, chmod, chdir, and getcwd

The filesystem code was using these functions without checking for their
existence, assuming that any UNIX-like libc with <unistd.h> would always
provide them. That's not true for some newlib targets like arm-eabi.

libstdc++-v3/ChangeLog:

	* acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for mkdir,
	chmod, chdir, and getcwd.
	* config.h.in: Regenerate.
	* configure: Regenerate.
	* src/c++17/fs_ops.cc (create_dir): Use USE_MKDIR macro.
	(fs::current_path): Use USE_GETCWD and USE_CHDIR macros.
	(fs::permissions): Use USE_CHMOD macro.
	* src/filesystem/ops-common.h [FILESYSTEM_IS_WINDOWS]
	(chmod, mkdir, getcwd, chdir): Define new macros.
	[FILESYSTEM_IS_WINDOWS] (chmod, mkdir, getcwd, chdir): Use
	new macros.
	* src/filesystem/ops.cc (create_dir): Use USE_MKDIR macro.
	(fs::current_path): Use USE_GETCWD and USE_CHDIR macros.
	(fs::permissions): Use USE_CHMOD macro.
This commit is contained in:
Jonathan Wakely 2023-09-07 17:03:40 +01:00
parent d295a5341d
commit 5435449be0
6 changed files with 355 additions and 9 deletions

View File

@ -4997,6 +4997,66 @@ dnl
if test $glibcxx_cv_dirent_d_type = yes; then
AC_DEFINE(HAVE_STRUCT_DIRENT_D_TYPE, 1, [Define to 1 if `d_type' is a member of `struct dirent'.])
fi
dnl
AC_CACHE_CHECK([for chmod], glibcxx_cv_chmod, [dnl
GCC_TRY_COMPILE_OR_LINK(
[
#include <sys/stat.h>
],
[
int i = chmod("", S_IRUSR);
],
[glibcxx_cv_chmod=yes],
[glibcxx_cv_chmod=no])
])
if test $glibcxx_cv_chmod = yes; then
AC_DEFINE(_GLIBCXX_USE_CHMOD, 1, [Define if usable chmod is available in <sys/stat.h>.])
fi
dnl
AC_CACHE_CHECK([for mkdir], glibcxx_cv_mkdir, [dnl
GCC_TRY_COMPILE_OR_LINK(
[
#include <sys/stat.h>
],
[
int i = mkdir("", S_IRUSR);
],
[glibcxx_cv_mkdir=yes],
[glibcxx_cv_mkdir=no])
])
if test $glibcxx_cv_mkdir = yes; then
AC_DEFINE(_GLIBCXX_USE_MKDIR, 1, [Define if usable mkdir is available in <sys/stat.h>.])
fi
dnl
AC_CACHE_CHECK([for chdir], glibcxx_cv_chdir, [dnl
GCC_TRY_COMPILE_OR_LINK(
[
#include <unistd.h>
],
[
int i = chdir("");
],
[glibcxx_cv_chdir=yes],
[glibcxx_cv_chdir=no])
])
if test $glibcxx_cv_chdir = yes; then
AC_DEFINE(_GLIBCXX_USE_CHDIR, 1, [Define if usable chdir is available in <unistd.h>.])
fi
dnl
AC_CACHE_CHECK([for getcwd], glibcxx_cv_getcwd, [dnl
GCC_TRY_COMPILE_OR_LINK(
[
#include <unistd.h>
],
[
char* s = getcwd((char*)0, 1);
],
[glibcxx_cv_getcwd=yes],
[glibcxx_cv_getcwd=no])
])
if test $glibcxx_cv_getcwd = yes; then
AC_DEFINE(_GLIBCXX_USE_GETCWD, 1, [Define if usable getcwd is available in <unistd.h>.])
fi
dnl
AC_CACHE_CHECK([for realpath], glibcxx_cv_realpath, [dnl
GCC_TRY_COMPILE_OR_LINK(

View File

@ -961,6 +961,12 @@
namespace std::tr1. */
#undef _GLIBCXX_USE_C99_STDINT_TR1
/* Define if usable chdir is available in <unistd.h>. */
#undef _GLIBCXX_USE_CHDIR
/* Define if usable chmod is available in <sys/stat.h>. */
#undef _GLIBCXX_USE_CHMOD
/* Defined if clock_gettime syscall has monotonic and realtime clock support.
*/
#undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL
@ -991,6 +997,9 @@
/* Define if fseeko and ftello are available. */
#undef _GLIBCXX_USE_FSEEKO_FTELLO
/* Define if usable getcwd is available in <unistd.h>. */
#undef _GLIBCXX_USE_GETCWD
/* Defined if gettimeofday is available. */
#undef _GLIBCXX_USE_GETTIMEOFDAY
@ -1009,6 +1018,9 @@
/* Define if lstat is available in <sys/stat.h>. */
#undef _GLIBCXX_USE_LSTAT
/* Define if usable mkdir is available in <sys/stat.h>. */
#undef _GLIBCXX_USE_MKDIR
/* Defined if nanosleep is available. */
#undef _GLIBCXX_USE_NANOSLEEP

252
libstdc++-v3/configure vendored
View File

@ -71838,6 +71838,258 @@ $as_echo "$glibcxx_cv_dirent_d_type" >&6; }
$as_echo "#define HAVE_STRUCT_DIRENT_D_TYPE 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for chmod" >&5
$as_echo_n "checking for chmod... " >&6; }
if ${glibcxx_cv_chmod+:} false; then :
$as_echo_n "(cached) " >&6
else
if test x$gcc_no_link = xyes; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/stat.h>
int
main ()
{
int i = chmod("", S_IRUSR);
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
glibcxx_cv_chmod=yes
else
glibcxx_cv_chmod=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
else
if test x$gcc_no_link = xyes; then
as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/stat.h>
int
main ()
{
int i = chmod("", S_IRUSR);
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
glibcxx_cv_chmod=yes
else
glibcxx_cv_chmod=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_chmod" >&5
$as_echo "$glibcxx_cv_chmod" >&6; }
if test $glibcxx_cv_chmod = yes; then
$as_echo "#define _GLIBCXX_USE_CHMOD 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mkdir" >&5
$as_echo_n "checking for mkdir... " >&6; }
if ${glibcxx_cv_mkdir+:} false; then :
$as_echo_n "(cached) " >&6
else
if test x$gcc_no_link = xyes; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/stat.h>
int
main ()
{
int i = mkdir("", S_IRUSR);
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
glibcxx_cv_mkdir=yes
else
glibcxx_cv_mkdir=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
else
if test x$gcc_no_link = xyes; then
as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/stat.h>
int
main ()
{
int i = mkdir("", S_IRUSR);
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
glibcxx_cv_mkdir=yes
else
glibcxx_cv_mkdir=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_mkdir" >&5
$as_echo "$glibcxx_cv_mkdir" >&6; }
if test $glibcxx_cv_mkdir = yes; then
$as_echo "#define _GLIBCXX_USE_MKDIR 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for chdir" >&5
$as_echo_n "checking for chdir... " >&6; }
if ${glibcxx_cv_chdir+:} false; then :
$as_echo_n "(cached) " >&6
else
if test x$gcc_no_link = xyes; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <unistd.h>
int
main ()
{
int i = chdir("");
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
glibcxx_cv_chdir=yes
else
glibcxx_cv_chdir=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
else
if test x$gcc_no_link = xyes; then
as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <unistd.h>
int
main ()
{
int i = chdir("");
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
glibcxx_cv_chdir=yes
else
glibcxx_cv_chdir=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_chdir" >&5
$as_echo "$glibcxx_cv_chdir" >&6; }
if test $glibcxx_cv_chdir = yes; then
$as_echo "#define _GLIBCXX_USE_CHDIR 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getcwd" >&5
$as_echo_n "checking for getcwd... " >&6; }
if ${glibcxx_cv_getcwd+:} false; then :
$as_echo_n "(cached) " >&6
else
if test x$gcc_no_link = xyes; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <unistd.h>
int
main ()
{
char* s = getcwd((char*)0, 1);
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
glibcxx_cv_getcwd=yes
else
glibcxx_cv_getcwd=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
else
if test x$gcc_no_link = xyes; then
as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <unistd.h>
int
main ()
{
char* s = getcwd((char*)0, 1);
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
glibcxx_cv_getcwd=yes
else
glibcxx_cv_getcwd=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_getcwd" >&5
$as_echo "$glibcxx_cv_getcwd" >&6; }
if test $glibcxx_cv_getcwd = yes; then
$as_echo "#define _GLIBCXX_USE_GETCWD 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for realpath" >&5
$as_echo_n "checking for realpath... " >&6; }

View File

@ -577,7 +577,7 @@ namespace
create_dir(const fs::path& p, fs::perms perm, std::error_code& ec)
{
bool created = false;
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
#if _GLIBCXX_USE_MKDIR
posix::mode_t mode = static_cast<std::underlying_type_t<fs::perms>>(perm);
if (posix::mkdir(p.c_str(), mode))
{
@ -735,7 +735,7 @@ fs::path
fs::current_path(error_code& ec)
{
path p;
#if defined _GLIBCXX_HAVE_UNISTD_H && ! defined __AVR__
#if _GLIBCXX_USE_GETCWD
#if defined __GLIBC__ || defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
if (char_ptr cwd = char_ptr{posix::getcwd(nullptr, 0)})
{
@ -783,7 +783,7 @@ fs::current_path(error_code& ec)
}
}
#endif // __GLIBC__
#else // _GLIBCXX_HAVE_UNISTD_H
#else // _GLIBCXX_USE_GETCWD
ec = std::make_error_code(std::errc::function_not_supported);
#endif
return p;
@ -801,7 +801,7 @@ fs::current_path(const path& p)
void
fs::current_path(const path& p, error_code& ec) noexcept
{
#ifdef _GLIBCXX_HAVE_UNISTD_H
#if _GLIBCXX_USE_CHDIR
if (posix::chdir(p.c_str()))
ec.assign(errno, std::generic_category());
else
@ -1097,6 +1097,7 @@ void
fs::permissions(const path& p, perms prms, perm_options opts,
error_code& ec) noexcept
{
#if _GLIBCXX_USE_FCHMODAT || _GLIBCXX_USE_CHMOD
const bool replace = is_set(opts, perm_options::replace);
const bool add = is_set(opts, perm_options::add);
const bool remove = is_set(opts, perm_options::remove);
@ -1138,6 +1139,9 @@ fs::permissions(const path& p, perms prms, perm_options opts,
ec.assign(err, std::generic_category());
else
ec.clear();
#else
ec = std::make_error_code(std::errc::function_not_supported);
#endif
}
fs::path

View File

@ -35,7 +35,7 @@
# endif
# if defined(_GLIBCXX_HAVE_SYS_STAT_H) && defined(_GLIBCXX_HAVE_SYS_TYPES_H)
# include <sys/types.h>
# include <sys/stat.h>
# include <sys/stat.h> // mkdir, chmod
# endif
#endif
#if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
@ -133,15 +133,19 @@ namespace __gnu_posix
inline int chmod(const wchar_t* path, mode_t mode)
{ return ::_wchmod(path, mode); }
#define _GLIBCXX_USE_CHMOD 1
inline int mkdir(const wchar_t* path, mode_t)
{ return ::_wmkdir(path); }
#define _GLIBCXX_USE_MKDIR 1
inline wchar_t* getcwd(wchar_t* buf, size_t size)
{ return ::_wgetcwd(buf, size > (size_t)INT_MAX ? INT_MAX : (int)size); }
#define _GLIBCXX_USE_GETCWD 1
inline int chdir(const wchar_t* path)
{ return ::_wchdir(path); }
#define _GLIBCXX_USE_CHDIR 1
#if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
using utimbuf = _utimbuf;
@ -190,10 +194,18 @@ namespace __gnu_posix
# endif
# endif
using ::mode_t;
# if _GLIBCXX_USE_CHMOD
using ::chmod;
# endif
# if _GLIBCXX_USE_MKDIR
using ::mkdir;
# endif
# if _GLIBCXX_USE_GETCWD
using ::getcwd;
# endif
# if _GLIBCXX_USE_CHDIR
using ::chdir;
# endif
# if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_USE_UTIME
using ::utimbuf;
using ::utime;
@ -549,8 +561,10 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
if (::fchmod(out.fd, from_st->st_mode))
#elif defined _GLIBCXX_USE_FCHMODAT && ! defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
if (::fchmodat(AT_FDCWD, to, from_st->st_mode, 0))
#else
#elif defined _GLIBCXX_USE_CHMOD
if (posix::chmod(to, from_st->st_mode))
#else
if (false)
#endif
{
ec.assign(errno, std::generic_category());

View File

@ -488,7 +488,7 @@ namespace
create_dir(const fs::path& p, fs::perms perm, std::error_code& ec)
{
bool created = false;
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
#if _GLIBCXX_USE_MKDIR
posix::mode_t mode = static_cast<std::underlying_type_t<fs::perms>>(perm);
if (posix::mkdir(p.c_str(), mode))
{
@ -645,7 +645,7 @@ fs::path
fs::current_path(error_code& ec)
{
path p;
#ifdef _GLIBCXX_HAVE_UNISTD_H
#if _GLIBCXX_USE_GETCWD
#if defined __GLIBC__ || defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
if (char_ptr cwd = char_ptr{posix::getcwd(nullptr, 0)})
{
@ -711,7 +711,7 @@ fs::current_path(const path& p)
void
fs::current_path(const path& p, error_code& ec) noexcept
{
#ifdef _GLIBCXX_HAVE_UNISTD_H
#if _GLIBCXX_USE_CHDIR
if (posix::chdir(p.c_str()))
ec.assign(errno, std::generic_category());
else
@ -947,6 +947,7 @@ fs::permissions(const path& p, perms prms)
void
fs::permissions(const path& p, perms prms, error_code& ec) noexcept
{
#if _GLIBCXX_USE_FCHMODAT || _GLIBCXX_USE_CHMOD
const bool add = is_set(prms, perms::add_perms);
const bool remove = is_set(prms, perms::remove_perms);
const bool nofollow = is_set(prms, perms::symlink_nofollow);
@ -987,6 +988,9 @@ fs::permissions(const path& p, perms prms, error_code& ec) noexcept
ec.assign(err, std::generic_category());
else
ec.clear();
#else
ec = std::make_error_code(std::errc::function_not_supported);
#endif
}
fs::path