diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2019-01-07 12:38:51 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2019-01-07 12:38:51 +0000 |
commit | cf4b581f2e28368c01fe93792ebc6eefb2bc8116 (patch) | |
tree | e97aa3a3f62308d35f617bfdfd0d7cc819e035dd | |
parent | f4bf2aabe36633d75852313caafe7efab71d5ba7 (diff) | |
download | gcc-cf4b581f2e28368c01fe93792ebc6eefb2bc8116.zip gcc-cf4b581f2e28368c01fe93792ebc6eefb2bc8116.tar.gz gcc-cf4b581f2e28368c01fe93792ebc6eefb2bc8116.tar.bz2 |
Fix build for systems without POSIX truncate
Older versions of newlib do not provide truncate so add a configure
check for it, and provide a fallback definition.
There were also some missing exports in the linker script, which went
unnoticed because there are no tests for some functions. A new link-only
test checks that every filesystem operation function is defined by the
library.
* acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for truncate.
* config.h.in: Regenerate.
* config/abi/pre/gnu.ver: Order patterns for filesystem operations
alphabetically and add missing entries for copy_symlink,
hard_link_count, rename, and resize_file.
* configure: Regenerate.
* src/c++17/fs_ops.cc (resize_file): Remove #if so posix::truncate is
used unconditionally.
* src/filesystem/ops-common.h (__gnu_posix::truncate)
[!_GLIBCXX_HAVE_TRUNCATE]: Provide fallback definition that only
supports truncating to zero length.
* testsuite/27_io/filesystem/operations/all.cc: New test.
* testsuite/27_io/filesystem/operations/resize_file.cc: New test.
From-SVN: r267647
-rw-r--r-- | libstdc++-v3/ChangeLog | 16 | ||||
-rw-r--r-- | libstdc++-v3/acinclude.m4 | 13 | ||||
-rw-r--r-- | libstdc++-v3/config.h.in | 3 | ||||
-rw-r--r-- | libstdc++-v3/config/abi/pre/gnu.ver | 44 | ||||
-rwxr-xr-x | libstdc++-v3/configure | 56 | ||||
-rw-r--r-- | libstdc++-v3/src/c++17/fs_ops.cc | 4 | ||||
-rw-r--r-- | libstdc++-v3/src/filesystem/ops-common.h | 19 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/27_io/filesystem/operations/all.cc | 188 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/27_io/filesystem/operations/resize_file.cc | 72 |
9 files changed, 391 insertions, 24 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7d21d89..274cf3f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,19 @@ +2019-01-07 Jonathan Wakely <jwakely@redhat.com> + + * acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for truncate. + * config.h.in: Regenerate. + * config/abi/pre/gnu.ver: Order patterns for filesystem operations + alphabetically and add missing entries for copy_symlink, + hard_link_count, rename, and resize_file. + * configure: Regenerate. + * src/c++17/fs_ops.cc (resize_file): Remove #if so posix::truncate is + used unconditionally. + * src/filesystem/ops-common.h (__gnu_posix::truncate) + [!_GLIBCXX_HAVE_TRUNCATE]: Provide fallback definition that only + supports truncating to zero length. + * testsuite/27_io/filesystem/operations/all.cc: New test. + * testsuite/27_io/filesystem/operations/resize_file.cc: New test. + 2019-01-06 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/86756 diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index ce91e49..8950e4c 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -4590,6 +4590,19 @@ dnl fi AC_MSG_RESULT($glibcxx_cv_symlink) dnl + AC_MSG_CHECKING([for truncate]) + AC_CACHE_VAL(glibcxx_cv_truncate, [dnl + GCC_TRY_COMPILE_OR_LINK( + [#include <unistd.h>], + [truncate("", 99);], + [glibcxx_cv_truncate=yes], + [glibcxx_cv_truncate=no]) + ]) + if test $glibcxx_cv_truncate = yes; then + AC_DEFINE(HAVE_TRUNCATE, 1, [Define if truncate is available in <unistd.h>.]) + fi + AC_MSG_RESULT($glibcxx_cv_truncate) +dnl CXXFLAGS="$ac_save_CXXFLAGS" AC_LANG_RESTORE fi diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index 97b5eed..225ef1b 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -511,6 +511,9 @@ /* Define to 1 if the target supports thread-local storage. */ #undef HAVE_TLS +/* Define if truncate is available in <unistd.h>. */ +#undef HAVE_TRUNCATE + /* Define to 1 if you have the <uchar.h> header file. */ #undef HAVE_UCHAR_H diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 20325bf..02a6ec9 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -2167,31 +2167,35 @@ GLIBCXX_3.4.26 { _ZNSt10filesystem7__cxx114pathpLERKS1_; _ZT[IV]NSt10filesystem7__cxx1116filesystem_errorE; - _ZNSt10filesystem10equivalent*; - _ZNSt10filesystem10remove_all*; - _ZNSt10filesystem11permissions*; - _ZNSt10filesystem12current_path*; - _ZNSt10filesystem12read_symlink*; - _ZNSt10filesystem14create_symlink*; - _ZNSt10filesystem14symlink_status*; - _ZNSt10filesystem15last_write_time*; - _ZNSt10filesystem16create_directory*; - _ZNSt10filesystem16create_hard_link*; - _ZNSt10filesystem16weakly_canonical*; - _ZNSt10filesystem18create_directories*; - _ZNSt10filesystem19temp_directory_path*; - _ZNSt10filesystem24create_directory_symlink*; - _ZNSt10filesystem4copy*; - _ZNSt10filesystem5space*; - _ZNSt10filesystem6remove*; - _ZNSt10filesystem6status*; _ZNSt10filesystem8absolute*; - _ZNSt10filesystem8is_empty*; - _ZNSt10filesystem8relative*; _ZNSt10filesystem9canonical*; + _ZNSt10filesystem4copy*; _ZNSt10filesystem9copy_file*; + _ZNSt10filesystem12copy_symlink*; + _ZNSt10filesystem18create_directories*; + _ZNSt10filesystem16create_directory*; + _ZNSt10filesystem24create_directory_symlink*; + _ZNSt10filesystem16create_hard_link*; + _ZNSt10filesystem14create_symlink*; + _ZNSt10filesystem12current_path*; + _ZNSt10filesystem10equivalent*; _ZNSt10filesystem9file_size*; + _ZNSt10filesystem15hard_link_count*; + _ZNSt10filesystem8is_empty*; + _ZNSt10filesystem15last_write_time*; + _ZNSt10filesystem11permissions*; _ZNSt10filesystem9proximate*; + _ZNSt10filesystem12read_symlink*; + _ZNSt10filesystem8relative*; + _ZNSt10filesystem6remove*; + _ZNSt10filesystem10remove_all*; + _ZNSt10filesystem6rename*; + _ZNSt10filesystem11resize_file*; + _ZNSt10filesystem5space*; + _ZNSt10filesystem6status*; + _ZNSt10filesystem14symlink_status*; + _ZNSt10filesystem19temp_directory_path*; + _ZNSt10filesystem16weakly_canonical*; _ZNKSt10filesystem18directory_iteratordeEv; _ZNKSt10filesystem28recursive_directory_iterator5depthEv; diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index e01d900..15848e3 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -81038,6 +81038,62 @@ $as_echo "#define HAVE_SYMLINK 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_symlink" >&5 $as_echo "$glibcxx_cv_symlink" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for truncate" >&5 +$as_echo_n "checking for truncate... " >&6; } + if ${glibcxx_cv_truncate+:} 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 () +{ +truncate("", 99); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + glibcxx_cv_truncate=yes +else + glibcxx_cv_truncate=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 () +{ +truncate("", 99); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + glibcxx_cv_truncate=yes +else + glibcxx_cv_truncate=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +fi + + if test $glibcxx_cv_truncate = yes; then + +$as_echo "#define HAVE_TRUNCATE 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_truncate" >&5 +$as_echo "$glibcxx_cv_truncate" >&6; } CXXFLAGS="$ac_save_CXXFLAGS" ac_ext=c ac_cpp='$CPP $CPPFLAGS' diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc index fd8cf35..edd9315 100644 --- a/libstdc++-v3/src/c++17/fs_ops.cc +++ b/libstdc++-v3/src/c++17/fs_ops.cc @@ -1268,16 +1268,12 @@ fs::resize_file(const path& p, uintmax_t size) void fs::resize_file(const path& p, uintmax_t size, error_code& ec) noexcept { -#ifdef _GLIBCXX_HAVE_UNISTD_H if (size > static_cast<uintmax_t>(std::numeric_limits<off_t>::max())) ec.assign(EINVAL, std::generic_category()); else if (posix::truncate(p.c_str(), size)) ec.assign(errno, std::generic_category()); else ec.clear(); -#else - ec = std::make_error_code(std::errc::not_supported); -#endif } diff --git a/libstdc++-v3/src/filesystem/ops-common.h b/libstdc++-v3/src/filesystem/ops-common.h index f20867c..55e482f 100644 --- a/libstdc++-v3/src/filesystem/ops-common.h +++ b/libstdc++-v3/src/filesystem/ops-common.h @@ -29,6 +29,9 @@ #ifdef _GLIBCXX_HAVE_UNISTD_H # include <unistd.h> +# ifdef _GLIBCXX_HAVE_FCNTL_H +# include <fcntl.h> // AT_FDCWD, O_TRUNC etc. +# endif # if defined(_GLIBCXX_HAVE_SYS_STAT_H) && defined(_GLIBCXX_HAVE_SYS_TYPES_H) # include <sys/types.h> # include <sys/stat.h> @@ -139,7 +142,23 @@ namespace __gnu_posix using ::utime; # endif using ::rename; +# ifdef _GLIBCXX_HAVE_TRUNCATE using ::truncate; +# else + inline int truncate(const char* path, off_t length) + { + if (length == 0) + { + const int fd = ::open(path, O_WRONLY|O_TRUNC); + if (fd == -1) + return fd; + ::close(fd); + return 0; + } + errno = ENOTSUP; + return -1; + } +# endif using char_type = char; #else // ! _GLIBCXX_FILESYSTEM_IS_WINDOWS && ! _GLIBCXX_HAVE_UNISTD_H inline int open(const char*, int, ...) { errno = ENOTSUP; return -1; } diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/all.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/all.cc new file mode 100644 index 0000000..c9f34f4 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/all.cc @@ -0,0 +1,188 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } + +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++17 -fno-inline" } +// { dg-do link { target c++17 } } + +// C++17 30.10.15 Filesystem operation functions [fs.op.funcs] + +#include <filesystem> + +// Link-only test to ensure all operation functions are exported from the lib. + +int +main() +{ + const std::filesystem::path p; + std::filesystem::path p2; + const std::filesystem::copy_options copyopts{}; + const std::filesystem::file_status st{}; + std::filesystem::file_status st2; + const std::filesystem::file_time_type t; + std::filesystem::file_time_type t2; + const std::filesystem::perms perms{}; + const std::filesystem::perm_options permopts{}; + std::filesystem::space_info sp; + std::error_code ec; + bool b; + std::uintmax_t size; + + std::filesystem::absolute(p); + std::filesystem::absolute(p, ec); + + std::filesystem::canonical(p); + std::filesystem::canonical(p, ec); + + std::filesystem::copy(p, p); + std::filesystem::copy(p, p, ec); + std::filesystem::copy(p, p, copyopts); + std::filesystem::copy(p, p, copyopts, ec); + + std::filesystem::copy_file(p, p); + std::filesystem::copy_file(p, p, ec); + std::filesystem::copy_file(p, p, copyopts); + std::filesystem::copy_file(p, p, copyopts, ec); + + std::filesystem::copy_symlink(p, p); + std::filesystem::copy_symlink(p, p, ec); + + std::filesystem::create_directories(p); + std::filesystem::create_directories(p, ec); + + std::filesystem::create_directory(p); + std::filesystem::create_directory(p, ec); + + std::filesystem::create_directory(p, p); + std::filesystem::create_directory(p, p, ec); + + std::filesystem::create_directory_symlink(p, p); + std::filesystem::create_directory_symlink(p, p, ec); + + std::filesystem::create_hard_link(p, p); + std::filesystem::create_hard_link(p, p, ec); + + std::filesystem::create_symlink(p, p); + std::filesystem::create_symlink(p, p, ec); + + p2 = std::filesystem::current_path(); + p2 = std::filesystem::current_path(ec); + std::filesystem::current_path(p); + std::filesystem::current_path(p, ec); + + b = std::filesystem::equivalent(p, p); + b = std::filesystem::equivalent(p, p, ec); + + b = std::filesystem::exists(st); + b = std::filesystem::exists(p); + b = std::filesystem::exists(p, ec); + + size = std::filesystem::file_size(p); + size = std::filesystem::file_size(p, ec); + + size = std::filesystem::hard_link_count(p); + size = std::filesystem::hard_link_count(p, ec); + + b = std::filesystem::is_block_file(st); + b = std::filesystem::is_block_file(p); + b = std::filesystem::is_block_file(p, ec); + + b = std::filesystem::is_character_file(st); + b = std::filesystem::is_character_file(p); + b = std::filesystem::is_character_file(p, ec); + + b = std::filesystem::is_directory(st); + b = std::filesystem::is_directory(p); + b = std::filesystem::is_directory(p, ec); + + b = std::filesystem::is_empty(p); + b = std::filesystem::is_empty(p, ec); + + b = std::filesystem::is_fifo(st); + b = std::filesystem::is_fifo(p); + b = std::filesystem::is_fifo(p, ec); + + b = std::filesystem::is_other(st); + b = std::filesystem::is_other(p); + b = std::filesystem::is_other(p, ec); + + b = std::filesystem::is_regular_file(st); + b = std::filesystem::is_regular_file(p); + b = std::filesystem::is_regular_file(p, ec); + + b = std::filesystem::is_socket(st); + b = std::filesystem::is_socket(p); + b = std::filesystem::is_socket(p, ec); + + b = std::filesystem::is_symlink(st); + b = std::filesystem::is_symlink(p); + b = std::filesystem::is_symlink(p, ec); + + t2 = std::filesystem::last_write_time(p); + t2 = std::filesystem::last_write_time(p, ec); + std::filesystem::last_write_time(p, t); + std::filesystem::last_write_time(p, t, ec); + + std::filesystem::permissions(p, perms); + std::filesystem::permissions(p, perms, permopts); + std::filesystem::permissions(p, perms, ec); + std::filesystem::permissions(p, perms, permopts, ec); + + p2 = std::filesystem::proximate(p, ec); + p2 = std::filesystem::proximate(p); + p2 = std::filesystem::proximate(p, p); + p2 = std::filesystem::proximate(p, p, ec); + + p2 = std::filesystem::read_symlink(p); + p2 = std::filesystem::read_symlink(p, ec); + + p2 = std::filesystem::relative(p, ec); + p2 = std::filesystem::relative(p); + p2 = std::filesystem::relative(p, p); + p2 = std::filesystem::relative(p, p, ec); + + b = std::filesystem::remove(p); + b = std::filesystem::remove(p, ec); + + size = std::filesystem::remove_all(p); + size = std::filesystem::remove_all(p, ec); + + std::filesystem::rename(p, p); + std::filesystem::rename(p, p, ec); + + std::filesystem::resize_file(p, size); + std::filesystem::resize_file(p, size, ec); + + sp = std::filesystem::space(p); + sp = std::filesystem::space(p, ec); + + st2 = std::filesystem::status(p); + st2 = std::filesystem::status(p, ec); + + b = std::filesystem::status_known(st); + + st2 = std::filesystem::symlink_status(p); + st2 = std::filesystem::symlink_status(p, ec); + + p2 = std::filesystem::temp_directory_path(); + p2 = std::filesystem::temp_directory_path(ec); + + p2 = std::filesystem::weakly_canonical(p); + p2 = std::filesystem::weakly_canonical(p, ec); +} diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/resize_file.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/resize_file.cc new file mode 100644 index 0000000..953c4e1 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/resize_file.cc @@ -0,0 +1,72 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } + +// C++17 30.10.15.33 Resize file [fs.op.resize_file] + +#include <filesystem> +#include <string> +#include <fstream> +#include <testsuite_fs.h> +#include <testsuite_hooks.h> + +void +test01() +{ + auto p = __gnu_test::nonexistent_path(); + std::error_code ec; + resize_file(p, 0, ec); + VERIFY( ec ); + ec = {}; + resize_file(p, 1, ec); + VERIFY( ec ); + + __gnu_test::scoped_file f(p); + std::ofstream{p} << "some text"; + std::ifstream fin; + std::string input; + +#ifdef _GLIBCXX_HAVE_TRUNCATE + resize_file(p, 4, ec); + VERIFY( !ec ); + fin.open(p); + getline(fin, input); + VERIFY( input.length() == 4 ); + fin.close(); + + resize_file(p, 2); + fin.open(p); + getline(fin, input); + VERIFY( input.length() == 2 ); + fin.close(); +#endif + + resize_file(p, 0, ec); + VERIFY( !ec ); + fin.open(p); + getline(fin, input); + VERIFY( input.length() == 0 ); + fin.close(); +} + +int +main() +{ + test01(); +} |