libstdc++: Avoid unconditional use of errc::not_supported [PR 99327]
The errc::not_supported constant is only defined if ENOTSUP is defined, which is not true for all targets. Many uses of errc::not_supported in the filesystem library do not actually match the intended meaning of ENOTSUP described by POSIX. They should be using ENOSYS instead (i.e. errc::function_not_supported). This change ensures that appropriate error codes are used by the filesystem library. The remaining uses of errc::not_supported are replaced with a call to a new helper function so that an alternative value will be used on targets that don't support errc::not_supported. Signed-off-by: Jonathan Wakely <jwakely@redhat.com> libstdc++-v3/ChangeLog: PR libstdc++/99327 * src/filesystem/ops-common.h (__unsupported): New function to return a suitable error code for missing functionality. (posix::off_t): New typedef. (posix::*): Set errno to ENOSYS instead of ENOTSUP for no-op fallback implementations. (do_copy_file): Replace uses of errc::not_supported. * src/c++17/fs_ops.cc (fs::copy, fs::copy_file, create_dir) (fs::create_directory, fs::create_directory_symlink) (fs::create_hard_link, fs::create_symlink, fs::current_path) (fs::equivalent, do_stat, fs::file_size, fs::hard_link_count) (fs::last_write_time, fs::permissions, fs::read_symlink): Replace uses of errc::not_supported. (fs::resize_file): Qualify off_t. * src/filesystem/ops.cc (fs::copy, fs::copy_file, create_dir) (fs::create_directory, fs::create_directory_symlink) (fs::create_hard_link, fs::create_symlink, fs::current_path) (fs::equivalent, do_stat, fs::file_size, fs::last_write_time) (fs::permissions, fs::read_symlink, fs::system_complete): Replace uses of errc::not_supported. (fs::resize_file): Qualify off_t and enable unconditionally. * testsuite/19_diagnostics/system_error/cons-1.cc: Likewise.
This commit is contained in:
parent
d71476c9df
commit
59ffa3e3db
|
@ -353,7 +353,7 @@ fs::copy(const path& from, const path& to, copy_options options,
|
|||
}
|
||||
if (is_other(f) || is_other(t))
|
||||
{
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::invalid_argument);
|
||||
return;
|
||||
}
|
||||
if (is_directory(f) && is_regular_file(t))
|
||||
|
@ -412,7 +412,7 @@ fs::copy(const path& from, const path& to, copy_options options,
|
|||
else
|
||||
ec.clear();
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -435,7 +435,7 @@ fs::copy_file(const path& from, const path& to, copy_options options,
|
|||
return do_copy_file(from.c_str(), to.c_str(), copy_file_options(options),
|
||||
nullptr, nullptr, ec);
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
@ -583,7 +583,7 @@ namespace
|
|||
created = true;
|
||||
}
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
return created;
|
||||
}
|
||||
|
@ -631,7 +631,7 @@ fs::create_directory(const path& p, const path& attributes,
|
|||
}
|
||||
return create_dir(p, static_cast<perms>(st.st_mode), ec);
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_function_not_supported);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
@ -652,7 +652,7 @@ fs::create_directory_symlink(const path& to, const path& new_symlink,
|
|||
error_code& ec) noexcept
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#else
|
||||
create_symlink(to, new_symlink, ec);
|
||||
#endif
|
||||
|
@ -684,7 +684,7 @@ fs::create_hard_link(const path& to, const path& new_hard_link,
|
|||
else
|
||||
ec = __last_system_error();
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -708,7 +708,7 @@ fs::create_symlink(const path& to, const path& new_symlink,
|
|||
else
|
||||
ec.clear();
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -776,7 +776,7 @@ fs::current_path(error_code& ec)
|
|||
}
|
||||
#endif // __GLIBC__
|
||||
#else // _GLIBCXX_HAVE_UNISTD_H
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
@ -799,7 +799,7 @@ fs::current_path(const path& p, error_code& ec) noexcept
|
|||
else
|
||||
ec.clear();
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -839,7 +839,7 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
|
|||
{
|
||||
if (is_other(s1) && is_other(s2))
|
||||
{
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::__unsupported();
|
||||
return false;
|
||||
}
|
||||
ec.clear();
|
||||
|
@ -897,7 +897,7 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
|
|||
ec.clear();
|
||||
return false;
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
@ -928,7 +928,7 @@ namespace
|
|||
ec.clear();
|
||||
return f(st);
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
return deflt;
|
||||
#endif
|
||||
}
|
||||
|
@ -953,10 +953,10 @@ fs::file_size(const path& p, error_code& ec) noexcept
|
|||
if (s.type == file_type::directory)
|
||||
ec = std::make_error_code(std::errc::is_a_directory);
|
||||
else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::__unsupported();
|
||||
}
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
@ -978,7 +978,7 @@ fs::hard_link_count(const path& p, error_code& ec) noexcept
|
|||
return do_stat(p, ec, std::mem_fn(&stat_type::st_nlink),
|
||||
static_cast<uintmax_t>(-1));
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
return static_cast<uintmax_t>(-1);
|
||||
#endif
|
||||
}
|
||||
|
@ -1026,7 +1026,7 @@ fs::last_write_time(const path& p, error_code& ec) noexcept
|
|||
},
|
||||
file_time_type::min());
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
return file_time_type::min();
|
||||
#endif
|
||||
}
|
||||
|
@ -1072,7 +1072,7 @@ fs::last_write_time(const path& p,
|
|||
else
|
||||
ec.clear();
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1121,7 +1121,7 @@ fs::permissions(const path& p, perms prms, perm_options opts,
|
|||
err = errno;
|
||||
#else
|
||||
if (nofollow && is_symlink(st))
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::__unsupported();
|
||||
else if (posix::chmod(p.c_str(), static_cast<posix::mode_t>(prms)))
|
||||
err = errno;
|
||||
#endif
|
||||
|
@ -1206,7 +1206,7 @@ fs::path fs::read_symlink(const path& p, error_code& ec)
|
|||
}
|
||||
while (true);
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
@ -1434,7 +1434,7 @@ fs::resize_file(const path& p, uintmax_t size)
|
|||
void
|
||||
fs::resize_file(const path& p, uintmax_t size, error_code& ec) noexcept
|
||||
{
|
||||
if (size > static_cast<uintmax_t>(std::numeric_limits<off_t>::max()))
|
||||
if (size > static_cast<uintmax_t>(std::numeric_limits<posix::off_t>::max()))
|
||||
ec.assign(EINVAL, std::generic_category());
|
||||
else if (posix::truncate(p.c_str(), size))
|
||||
ec.assign(errno, std::generic_category());
|
||||
|
|
|
@ -69,6 +69,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
#endif
|
||||
}
|
||||
|
||||
// Get an error code indicating unsupported functionality.
|
||||
//
|
||||
// This should be used when a function is unable to behave as specified
|
||||
// due to an incomplete or partial implementation, e.g.
|
||||
// filesystem::equivalent(a, b) if is_other(a) && is_other(b) is true.
|
||||
//
|
||||
// Use errc::function_not_supported for functions that are entirely
|
||||
// unimplemented, e.g. create_symlink on Windows.
|
||||
//
|
||||
// Use errc::invalid_argument for requests to perform operations outside
|
||||
// the spec, e.g. trying to copy a directory using filesystem::copy_file.
|
||||
inline error_code
|
||||
__unsupported() noexcept
|
||||
{
|
||||
#if defined ENOTSUP
|
||||
return std::make_error_code(std::errc::not_supported);
|
||||
#elif defined EOPNOTSUPP
|
||||
// This is supposed to be for socket operations
|
||||
return std::make_error_code(std::errc::operation_not_supported);
|
||||
#else
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace filesystem
|
||||
{
|
||||
namespace __gnu_posix
|
||||
|
@ -128,6 +152,7 @@ namespace __gnu_posix
|
|||
return -1;
|
||||
}
|
||||
|
||||
using off_t = _off64_t;
|
||||
inline int truncate(const wchar_t* path, _off64_t length)
|
||||
{
|
||||
const int fd = ::_wopen(path, _O_BINARY|_O_RDWR);
|
||||
|
@ -164,6 +189,7 @@ namespace __gnu_posix
|
|||
using ::utime;
|
||||
# endif
|
||||
using ::rename;
|
||||
using ::off_t;
|
||||
# ifdef _GLIBCXX_HAVE_TRUNCATE
|
||||
using ::truncate;
|
||||
# else
|
||||
|
@ -183,15 +209,16 @@ namespace __gnu_posix
|
|||
# endif
|
||||
using char_type = char;
|
||||
#else // ! _GLIBCXX_FILESYSTEM_IS_WINDOWS && ! _GLIBCXX_HAVE_UNISTD_H
|
||||
inline int open(const char*, int, ...) { errno = ENOTSUP; return -1; }
|
||||
inline int close(int) { errno = ENOTSUP; return -1; }
|
||||
inline int open(const char*, int, ...) { errno = ENOSYS; return -1; }
|
||||
inline int close(int) { errno = ENOSYS; return -1; }
|
||||
using mode_t = int;
|
||||
inline int chmod(const char*, mode_t) { errno = ENOTSUP; return -1; }
|
||||
inline int mkdir(const char*, mode_t) { errno = ENOTSUP; return -1; }
|
||||
inline char* getcwd(char*, size_t) { errno = ENOTSUP; return nullptr; }
|
||||
inline int chdir(const char*) { errno = ENOTSUP; return -1; }
|
||||
inline int rename(const char*, const char*) { errno = ENOTSUP; return -1; }
|
||||
inline int truncate(const char*, long) { errno = ENOTSUP; return -1; }
|
||||
inline int chmod(const char*, mode_t) { errno = ENOSYS; return -1; }
|
||||
inline int mkdir(const char*, mode_t) { errno = ENOSYS; return -1; }
|
||||
inline char* getcwd(char*, size_t) { errno = ENOSYS; return nullptr; }
|
||||
inline int chdir(const char*) { errno = ENOSYS; return -1; }
|
||||
inline int rename(const char*, const char*) { errno = ENOSYS; return -1; }
|
||||
using off_t = long;
|
||||
inline int truncate(const char*, off_t) { errno = ENOSYS; return -1; }
|
||||
using char_type = char;
|
||||
#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
} // namespace __gnu_posix
|
||||
|
@ -374,7 +401,7 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
|
|||
// 2712. copy_file() has a number of unspecified error conditions
|
||||
if (!is_regular_file(f))
|
||||
{
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::invalid_argument);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -382,7 +409,7 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
|
|||
{
|
||||
if (!is_regular_file(t))
|
||||
{
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::invalid_argument);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -413,7 +440,7 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
|
|||
}
|
||||
else if (!is_regular_file(t))
|
||||
{
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::invalid_argument);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -572,7 +599,7 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
|
|||
else
|
||||
ec = std::last_system_error();
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
|
|
@ -293,7 +293,7 @@ fs::copy(const path& from, const path& to, copy_options options,
|
|||
}
|
||||
if (is_other(f) || is_other(t))
|
||||
{
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::invalid_argument);
|
||||
return;
|
||||
}
|
||||
if (is_directory(f) && is_regular_file(t))
|
||||
|
@ -372,7 +372,7 @@ fs::copy_file(const path& from, const path& to, copy_options options,
|
|||
return do_copy_file(from.c_str(), to.c_str(), copy_file_options(options),
|
||||
nullptr, nullptr, ec);
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
@ -491,7 +491,7 @@ namespace
|
|||
created = true;
|
||||
}
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
return created;
|
||||
}
|
||||
|
@ -539,7 +539,7 @@ fs::create_directory(const path& p, const path& attributes,
|
|||
}
|
||||
return create_dir(p, static_cast<perms>(st.st_mode), ec);
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
@ -560,7 +560,7 @@ fs::create_directory_symlink(const path& to, const path& new_symlink,
|
|||
error_code& ec) noexcept
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#else
|
||||
create_symlink(to, new_symlink, ec);
|
||||
#endif
|
||||
|
@ -592,7 +592,7 @@ fs::create_hard_link(const path& to, const path& new_hard_link,
|
|||
else
|
||||
ec = __last_system_error();
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -616,7 +616,7 @@ fs::create_symlink(const path& to, const path& new_symlink,
|
|||
else
|
||||
ec.clear();
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -683,7 +683,7 @@ fs::current_path(error_code& ec)
|
|||
}
|
||||
#endif // __GLIBC__
|
||||
#else // _GLIBCXX_HAVE_UNISTD_H
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
@ -706,7 +706,7 @@ fs::current_path(const path& p, error_code& ec) noexcept
|
|||
else
|
||||
ec.clear();
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -746,7 +746,7 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
|
|||
{
|
||||
if (is_other(s1) && is_other(s2))
|
||||
{
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::__unsupported();
|
||||
return false;
|
||||
}
|
||||
ec.clear();
|
||||
|
@ -762,7 +762,7 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
|
|||
ec.clear();
|
||||
return false;
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
@ -793,7 +793,7 @@ namespace
|
|||
ec.clear();
|
||||
return f(st);
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
return deflt;
|
||||
#endif
|
||||
}
|
||||
|
@ -817,7 +817,7 @@ fs::file_size(const path& p, error_code& ec) noexcept
|
|||
if (s.type == file_type::directory)
|
||||
ec = std::make_error_code(std::errc::is_a_directory);
|
||||
else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::__unsupported();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -920,7 +920,7 @@ fs::last_write_time(const path& p __attribute__((__unused__)),
|
|||
else
|
||||
ec.clear();
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -967,7 +967,7 @@ fs::permissions(const path& p, perms prms, error_code& ec) noexcept
|
|||
err = errno;
|
||||
#else
|
||||
if (nofollow && is_symlink(st))
|
||||
ec = std::make_error_code(std::errc::operation_not_supported);
|
||||
ec = std::__unsupported();
|
||||
else if (posix::chmod(p.c_str(), static_cast<mode_t>(prms)))
|
||||
err = errno;
|
||||
#endif
|
||||
|
@ -1032,7 +1032,7 @@ fs::path fs::read_symlink(const path& p [[gnu::unused]], error_code& ec)
|
|||
}
|
||||
while (true);
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::make_error_code(std::errc::function_not_supported);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
@ -1153,16 +1153,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()))
|
||||
if (size > static_cast<uintmax_t>(std::numeric_limits<posix::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
|
||||
}
|
||||
|
||||
|
||||
|
@ -1280,7 +1276,7 @@ fs::system_complete(const path& p, error_code& ec)
|
|||
|| p.root_name() == base.root_name())
|
||||
return absolute(p, base);
|
||||
// else TODO
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
ec = std::__unsupported();
|
||||
return {};
|
||||
#else
|
||||
if (ec.value())
|
||||
|
|
|
@ -26,19 +26,19 @@ int main()
|
|||
{
|
||||
const std::string s("too late: boulangerie out of pain au raisin");
|
||||
const std::error_code
|
||||
e(std::make_error_code(std::errc::operation_not_supported));
|
||||
e(std::make_error_code(std::errc::invalid_argument));
|
||||
|
||||
// 1
|
||||
{
|
||||
std::system_error err1(e, s);
|
||||
VERIFY( err1.code() == e );
|
||||
VERIFY( err1.code() == e );
|
||||
VERIFY( std::string(err1.what()).find(s) != std::string::npos );
|
||||
}
|
||||
|
||||
// 2
|
||||
{
|
||||
std::system_error err2(95, std::system_category(), s);
|
||||
VERIFY( err2.code() == std::error_code(95, std::system_category()) );
|
||||
VERIFY( err2.code() == std::error_code(95, std::system_category()) );
|
||||
VERIFY( std::string((err2.what(), s)).find(s) != std::string::npos );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue