diff --git a/runtime-light/stdlib/file/file-system-functions.h b/runtime-light/stdlib/file/file-system-functions.h index bdc3ece9c7..5a84100fe2 100644 --- a/runtime-light/stdlib/file/file-system-functions.h +++ b/runtime-light/stdlib/file/file-system-functions.h @@ -16,9 +16,7 @@ #include #include -#include "runtime-common/core/allocator/script-allocator.h" #include "runtime-common/core/runtime-core.h" -#include "runtime-common/core/std/containers.h" #include "runtime-common/stdlib/array/array-functions.h" #include "runtime-common/stdlib/string/string-functions.h" #include "runtime-light/coroutine/task.h" @@ -204,40 +202,22 @@ inline Optional f$file_get_contents(const string& stream) noexcept { } inline Optional> f$file(const string& name) noexcept { - struct stat stat_buf {}; - auto expected_file{kphp::fs::file::open(name.c_str(), "r")}; if (!expected_file.has_value()) { return false; } - if (!k2::stat({name.c_str(), name.size()}, std::addressof(stat_buf)).has_value()) { - return false; - } - if (!S_ISREG(stat_buf.st_mode)) { - kphp::log::warning("regular file expected as first argument in function file, \"{}\" is given", name.c_str()); - return false; - } - const size_t size{static_cast(stat_buf.st_size)}; - if (size > string::max_size()) { - kphp::log::warning("file \"{}\" is too large", name.c_str()); + auto expected_file_content{std::move(*expected_file).get_contents()}; + if (!expected_file_content.has_value()) { return false; } - - kphp::stl::vector file_content; - file_content.resize(size); - { - auto file{std::move(*expected_file)}; - if (auto expected_read_result{file.read(file_content)}; !expected_read_result.has_value() || *expected_read_result < size) { - return false; - } - } + auto file_content{std::move(*expected_file_content)}; array result; int32_t prev{-1}; - for (size_t i{0}; i < size; i++) { - if (static_cast(file_content[i]) == '\n' || i + 1 == size) { - result.push_back(string{reinterpret_cast(file_content.data()) + prev + 1, static_cast(i - prev)}); + for (size_t i{0}; i < file_content.size(); i++) { + if (static_cast(file_content[i]) == '\n' || i + 1 == file_content.size()) { + result.push_back(string{file_content.buffer() + prev + 1, static_cast(i - prev)}); prev = i; } } diff --git a/runtime-light/stdlib/file/resource.h b/runtime-light/stdlib/file/resource.h index 5300ce96e0..0db50450a0 100644 --- a/runtime-light/stdlib/file/resource.h +++ b/runtime-light/stdlib/file/resource.h @@ -17,6 +17,8 @@ #include #include +#include + #include "runtime-common/core/allocator/script-allocator.h" #include "runtime-common/core/class-instance/refcountable-php-classes.h" #include "runtime-common/core/runtime-core.h" @@ -25,6 +27,7 @@ #include "runtime-light/coroutine/task.h" #include "runtime-light/k2-platform/k2-api.h" #include "runtime-light/server/http/http-server-state.h" +#include "runtime-light/stdlib/diagnostics/logs.h" #include "runtime-light/stdlib/output/output-state.h" #include "runtime-light/streams/stream.h" @@ -146,7 +149,29 @@ inline auto file::pread(std::span buf, uint64_t offset) noexcept -> s } inline auto file::get_contents() noexcept -> std::expected { - return std::unexpected{m_descriptor != k2::INVALID_PLATFORM_DESCRIPTOR ? k2::errno_efault : k2::errno_enodev}; + struct stat stat_buf {}; + + return k2::fstat(m_descriptor, std::addressof(stat_buf)).and_then([&stat_buf, this] noexcept -> std::expected { + if (!S_ISREG(stat_buf.st_mode)) { + kphp::log::warning("regular file expected"); + return std::unexpected{k2::errno_efault}; + } + + const size_t size{static_cast(stat_buf.st_size)}; + if (size > string::max_size()) { + kphp::log::warning("file is too large"); + return std::unexpected{k2::errno_efault}; + } + + string file_content{static_cast(size), false}; + return read({reinterpret_cast(file_content.buffer()), file_content.size()}) + .and_then([size, &file_content](size_t read_result) noexcept -> std::expected { + if (read_result < size) { + return std::unexpected{k2::errno_efault}; + } + return file_content; + }); + }); } inline auto file::flush() noexcept -> std::expected {