diff options
author | Eric Fiselier <eric@efcs.ca> | 2019-01-17 02:59:28 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2019-01-17 02:59:28 +0000 |
commit | 0e997efd53e839c6f34d470ecf89bd1c734ea94b (patch) | |
tree | 273d43d9e5ba76113f905e603f836b15236bf8df /libcxx | |
parent | [WebAssembly] Parse llvm.ident into producers section (diff) | |
download | llvm-project-0e997efd53e839c6f34d470ecf89bd1c734ea94b.tar.gz llvm-project-0e997efd53e839c6f34d470ecf89bd1c734ea94b.tar.bz2 llvm-project-0e997efd53e839c6f34d470ecf89bd1c734ea94b.zip |
[hurd] Fix unconditional use of PATH_MAX
Patch by Samuel Thibault
The GNU/Hurd system does not define an arbitrary PATH_MAX limitation, the POSIX 2001 realpath
extension can be used instead, and the size of symlinks can be determined.
Reviewed as https://reviews.llvm.org/D54677
llvm-svn: 351414
Diffstat (limited to 'libcxx')
-rw-r--r-- | libcxx/src/filesystem/operations.cpp | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp index b41061888724..54a234e5ffb6 100644 --- a/libcxx/src/filesystem/operations.cpp +++ b/libcxx/src/filesystem/operations.cpp @@ -543,11 +543,19 @@ path __canonical(path const& orig_p, error_code* ec) { ErrorHandler<path> err("canonical", ec, &orig_p, &cwd); path p = __do_absolute(orig_p, &cwd, ec); +#if _POSIX_VERSION >= 200112 + std::unique_ptr<char, decltype(&::free)> + hold(::realpath(p.c_str(), nullptr), &::free); + if (hold.get() == nullptr) + return err.report(capture_errno()); + return {hold.get()}; +#else char buff[PATH_MAX + 1]; char* ret; if ((ret = ::realpath(p.c_str(), buff)) == nullptr) return err.report(capture_errno()); return {ret}; +#endif } void __copy(const path& from, const path& to, copy_options options, @@ -1089,16 +1097,27 @@ void __permissions(const path& p, perms prms, perm_options opts, path __read_symlink(const path& p, error_code* ec) { ErrorHandler<path> err("read_symlink", ec, &p); - char buff[PATH_MAX + 1]; - error_code m_ec; - ::ssize_t ret; - if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) { +#ifdef PATH_MAX + struct NullDeleter { void operator()(void*) const {} }; + const size_t size = PATH_MAX + 1; + char stack_buff[size]; + auto buff = std::unique_ptr<char[], NullDeleter>(stack_buff); +#else + StatT sb; + if (::lstat(p.c_str(), &sb) == -1) { return err.report(capture_errno()); } - _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO"); + const size_t size = sb.st_size + 1; + auto buff = unique_ptr<char[]>(new char[size]); +#endif + ::ssize_t ret; + if ((ret = ::readlink(p.c_str(), buff.get(), size)) == -1) + return err.report(capture_errno()); _LIBCPP_ASSERT(ret > 0, "TODO"); + if (static_cast<size_t>(ret) >= size) + return err.report(errc::value_too_large); buff[ret] = 0; - return {buff}; + return {buff.get()}; } bool __remove(const path& p, error_code* ec) { |