commit 56ea87282c8489752e54c45d0e4b68823c59b670 from: Aleksey Ryndin date: Wed Aug 30 12:50:27 2023 UTC Before MIME: return opened file path commit - c2939b27ec9c1ba93e59bd04d1001c1780cf25e7 commit + 56ea87282c8489752e54c45d0e4b68823c59b670 blob - dd9e363064e1368f3b90a3e93c374093dd942de1 blob + 490a7207b488c0f90940fda93e95a002abeb7a66 --- tests/test_open_file.cc +++ tests/test_open_file.cc @@ -18,7 +18,28 @@ namespace error std::ostream dev_null{nullptr}; std::ostream &g_log = dev_null; } +namespace +{ +template +void fill(std::vector &v, const char (&arr)[N]) +{ + v.resize(N); + std::copy(&arr[0], &arr[N], v.begin()); +} +template +bool is_tail(Span opened_path, const char (&arr)[N]) +{ + if (opened_path.size() >= (N - 1)) + { + opened_path = opened_path.subspan(opened_path.size() - (N - 1)); + return std::equal(opened_path.begin(), opened_path.end(), &arr[0]); + } + return false; +} + +} // namespace + TEST_START(test_open_file) std::ostringstream ss; ss << "/tmp/test_open_file." << getpid() << "." << time(nullptr); @@ -27,11 +48,20 @@ TEST_START(test_open_file) const UniqueFd dir{open(ss.str().c_str(), O_RDONLY | O_DIRECTORY)}; IS_TRUE_ERRNO(dir, "Open directory " << ss.str().c_str()); + + std::vector sz_file_name; + Span opened_path; { UniqueFd opened_file; - IS_TRUE(open_file(dir.get(), "", opened_file) == FILE_NOT_FOUND and !opened_file); - IS_TRUE(open_file(dir.get(), "non-existent-file", opened_file) == FILE_NOT_FOUND and !opened_file); - IS_TRUE(open_file(dir.get(), "non-existent-dir/file", opened_file) == FILE_NOT_FOUND and !opened_file); + + fill(sz_file_name, ""); + IS_TRUE(open_file(dir.get(), sz_file_name , opened_file, opened_path) == FILE_NOT_FOUND and !opened_file); + + fill(sz_file_name, "non-existent-file"); + IS_TRUE(open_file(dir.get(), sz_file_name, opened_file, opened_path) == FILE_NOT_FOUND and !opened_file); + + fill(sz_file_name, "non-existent-dir/file"); + IS_TRUE(open_file(dir.get(), sz_file_name, opened_file, opened_path) == FILE_NOT_FOUND and !opened_file); } const UniqueFd index_gmi{openat(dir.get(), "index.gmi", O_RDONLY | O_CREAT | O_EXCL, S_IRWXU)}; @@ -41,7 +71,10 @@ TEST_START(test_open_file) { UniqueFd opened_file; - IS_TRUE(open_file(dir.get(), "", opened_file) == FILE_OPENED and opened_file); + fill(sz_file_name, ""); + IS_TRUE(open_file(dir.get(), sz_file_name, opened_file, opened_path) == FILE_OPENED and opened_file); + IS_TRUE(is_tail(opened_path, "index.gmi")); + struct stat sb2{}; IS_TRUE_ERRNO(fstat(opened_file.get(), &sb2) != -1, "Stat file " << ss.str().c_str() << "/index.gmi"); IS_TRUE((sb1.st_dev == sb2.st_dev) && (sb1.st_ino == sb2.st_ino)); @@ -49,7 +82,9 @@ TEST_START(test_open_file) { UniqueFd opened_file; - IS_TRUE(open_file(dir.get(), "index.gmi", opened_file) == FILE_OPENED and opened_file); + fill(sz_file_name, "index.gmi"); + IS_TRUE(open_file(dir.get(), sz_file_name, opened_file, opened_path) == FILE_OPENED and opened_file); + IS_TRUE(is_tail(opened_path, "index.gmi")); struct stat sb2{}; IS_TRUE_ERRNO(fstat(opened_file.get(), &sb2) != -1, "Stat file " << ss.str().c_str() << "/index.gmi"); IS_TRUE((sb1.st_dev == sb2.st_dev) && (sb1.st_ino == sb2.st_ino)); @@ -58,8 +93,10 @@ TEST_START(test_open_file) IS_TRUE_ERRNO(mkdirat(dir.get(), "subdir", S_IRWXU) != -1, "Create directory " << ss.str().c_str() << "/subdir"); { UniqueFd opened_file; - IS_TRUE(open_file(dir.get(), "subdir", opened_file) == FILE_NOT_FOUND and !opened_file); - IS_TRUE(open_file(dir.get(), "subdir/", opened_file) == FILE_NOT_FOUND and !opened_file); + fill(sz_file_name, "subdir"); + IS_TRUE(open_file(dir.get(), sz_file_name, opened_file, opened_path) == FILE_NOT_FOUND and !opened_file); + fill(sz_file_name, "subdir/"); + IS_TRUE(open_file(dir.get(), sz_file_name, opened_file, opened_path) == FILE_NOT_FOUND and !opened_file); } const UniqueFd subdir{openat(dir.get(), "subdir", O_RDONLY | O_DIRECTORY)}; IS_TRUE_ERRNO(subdir, "Open directory " << ss.str().c_str() << "/subdir"); @@ -70,7 +107,9 @@ TEST_START(test_open_file) { UniqueFd opened_file; - IS_TRUE(open_file(dir.get(), "subdir", opened_file) == FILE_OPENED and opened_file); + fill(sz_file_name, "subdir"); + IS_TRUE(open_file(dir.get(), sz_file_name, opened_file, opened_path) == FILE_OPENED and opened_file); + IS_TRUE(is_tail(opened_path, "index.gmi")); struct stat sb2{}; IS_TRUE_ERRNO(fstat(opened_file.get(), &sb2) != -1, "Stat file " << ss.str().c_str() << "/subdir/index.gmi"); IS_TRUE((sb1.st_dev == sb2.st_dev) && (sb1.st_ino == sb2.st_ino)); @@ -78,7 +117,9 @@ TEST_START(test_open_file) { UniqueFd opened_file; - IS_TRUE(open_file(dir.get(), "subdir/", opened_file) == FILE_OPENED and opened_file); + fill(sz_file_name, "subdir/"); + IS_TRUE(open_file(dir.get(), sz_file_name, opened_file, opened_path) == FILE_OPENED and opened_file); + IS_TRUE(is_tail(opened_path, "index.gmi")); struct stat sb2{}; IS_TRUE_ERRNO(fstat(opened_file.get(), &sb2) != -1, "Stat file " << ss.str().c_str() << "/subdir/index.gmi"); IS_TRUE((sb1.st_dev == sb2.st_dev) && (sb1.st_ino == sb2.st_ino)); @@ -86,7 +127,9 @@ TEST_START(test_open_file) { UniqueFd opened_file; - IS_TRUE(open_file(dir.get(), "subdir/index.gmi", opened_file) == FILE_OPENED and opened_file); + fill(sz_file_name, "subdir/index.gmi"); + IS_TRUE(open_file(dir.get(), sz_file_name, opened_file, opened_path) == FILE_OPENED and opened_file); + IS_TRUE(is_tail(opened_path, "index.gmi")); struct stat sb2{}; IS_TRUE_ERRNO(fstat(opened_file.get(), &sb2) != -1, "Stat file " << ss.str().c_str() << "/subdir/index.gmi"); IS_TRUE((sb1.st_dev == sb2.st_dev) && (sb1.st_ino == sb2.st_ino)); @@ -97,7 +140,8 @@ TEST_START(test_open_file) { UniqueFd opened_file; - IS_TRUE(open_file(dir.get(), "subdir/EPERM.gmi", opened_file) == FILE_OPENING_ERROR and !opened_file); + fill(sz_file_name, "subdir/EPERM.gmi"); + IS_TRUE(open_file(dir.get(), sz_file_name, opened_file, opened_path) == FILE_OPENING_ERROR and !opened_file); } IS_TRUE_ERRNO(unlinkat(subdir.get(), "EPERM.gmi", 0) != -1, "Remove file " << ss.str().c_str() << "/subdir/EPERM.gmi"); blob - 1fa3fbf6f7544b1b63f6fdfb18cabea02fe971c2 blob + bf7fc548d06c4122ff18d59004d8010ca6c8636c --- vostok/open_file.cc +++ vostok/open_file.cc @@ -11,14 +11,28 @@ namespace vostok { namespace { -NotNull index_gmi = "index.gmi"; +const char index_gmi[] = "index.gmi"; } // namespace -OpenFileResult open_file(int directory_fd, NotNull file_name, UniqueFd &opened_file) +OpenFileResult +open_file( + /* in */ int directory_fd, + /* in */ const std::vector &sz_file_name, + /* out */ UniqueFd &opened_file, + /* out */ Span &opened_path +) { + assert(sz_file_name.size()); + + NotNull file_name = sz_file_name.data(); + opened_path = cut_null(sz_file_name); + if (!*file_name) + { file_name = index_gmi; + opened_path = cut_null(index_gmi); + } opened_file.reset(openat(directory_fd, file_name, O_RDONLY)); if (!opened_file) @@ -48,6 +62,7 @@ OpenFileResult open_file(int directory_fd, NotNull file_name, UniqueFd &opened_file); +OpenFileResult +open_file( + /* in */ int directory_fd, + /* in */ const std::vector &sz_file_name, + /* out */ UniqueFd &opened_file, + /* out */ Span &opened_path +); + } // namespace vostok blob - e4e5c5bc74e604ca45c322c02d57bed199bdacdf blob + 08c3def08a75168b755be2465e2b8845f5f517c3 --- vostok/transport.h +++ vostok/transport.h @@ -1,8 +1,6 @@ /** Wrap libtls for gemini protocol */ #include "utils.h" - -#include #include #pragma once blob - bfc80dc82debb13758a5c46e0f023349e7870537 blob + 60749f41c58b753468d478666c6e0568f18c687b --- vostok/utils.h +++ vostok/utils.h @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -72,6 +73,20 @@ class Span (public) constexpr Span(element_type (&arr)[N]) : m_p{arr}, m_count{N} {} template constexpr Span(const std::array &arr) : m_p{arr.data()}, m_count{N} {} + template + Span(const std::vector &v) + { + if (v.size()) + { + m_p = v.data(); + m_count = v.size(); + } + else + { + m_p = nullptr; + m_count = 0; + } + } constexpr std::size_t size() const {return m_count;} @@ -108,6 +123,13 @@ constexpr Span cut_null(const char (&arr)[ static_assert(N > 0, "!(N > 0)"); return Span{arr, N - 1}; } +template +Span cut_null(const std::vector &v) +{ + assert(v.size() > 0); + assert(v[v.size() - 1] == '\0'); + return Span{v.data(), v.size() - 1}; +} /** Smart pointer for file descriptor */ blob - d4370280c07bcdf629918760944ebc867e2974ae blob + 35c28e6faddbc3bc9f924773c695981ddadef313 --- vostok/vostok.cc +++ vostok/vostok.cc @@ -12,7 +12,6 @@ #include #include -#include namespace vostok @@ -94,7 +93,8 @@ void client_thread(const transport::AcceptedClient *ac } UniqueFd opened_file{}; - const auto open_file_result = open_file(directory_fd, request.get_path().data(), opened_file); + Span opened_path; + const auto open_file_result = open_file(directory_fd, request.get_path(), opened_file, opened_path); switch (open_file_result) { case FILE_NOT_FOUND: