commit - c2939b27ec9c1ba93e59bd04d1001c1780cf25e7
commit + 56ea87282c8489752e54c45d0e4b68823c59b670
blob - dd9e363064e1368f3b90a3e93c374093dd942de1
blob + 490a7207b488c0f90940fda93e95a002abeb7a66
--- tests/test_open_file.cc
+++ tests/test_open_file.cc
std::ostream dev_null{nullptr};
std::ostream &g_log = dev_null;
}
+namespace
+{
+template <std::size_t N>
+void fill(std::vector<char> &v, const char (&arr)[N])
+{
+ v.resize(N);
+ std::copy(&arr[0], &arr[N], v.begin());
+}
+template <std::size_t N>
+bool is_tail(Span<const char> 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 <unnamed>
+
TEST_START(test_open_file)
std::ostringstream ss;
ss << "/tmp/test_open_file." << getpid() << "." << time(nullptr);
const UniqueFd dir{open(ss.str().c_str(), O_RDONLY | O_DIRECTORY)};
IS_TRUE_ERRNO(dir, "Open directory " << ss.str().c_str());
+
+ std::vector<char> sz_file_name;
+ Span<const char> 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)};
{
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));
{
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));
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");
{
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));
{
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));
{
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));
{
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
{
namespace
{
-NotNull<czstring> index_gmi = "index.gmi";
+const char index_gmi[] = "index.gmi";
} // namespace <unnamed>
-OpenFileResult open_file(int directory_fd, NotNull<czstring> file_name, UniqueFd &opened_file)
+OpenFileResult
+open_file(
+ /* in */ int directory_fd,
+ /* in */ const std::vector<char> &sz_file_name,
+ /* out */ UniqueFd &opened_file,
+ /* out */ Span<const char> &opened_path
+)
{
+ assert(sz_file_name.size());
+
+ NotNull<czstring> 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)
if (S_ISDIR(sb.st_mode))
{
const UniqueFd new_parent{opened_file.release()};
+ opened_path = cut_null(index_gmi);
opened_file.reset(openat(new_parent.get(), index_gmi, O_RDONLY));
if (!opened_file)
{
blob - a16a4bda08cbdc43ea3f7d423708326518d3166d
blob + a69a53ff70dbd260bb80d14e0faa7e9017c6584a
--- vostok/open_file.h
+++ vostok/open_file.h
FILE_NOT_FOUND,
FILE_OPENING_ERROR,
};
-OpenFileResult open_file(int directory_fd, NotNull<czstring> file_name, UniqueFd &opened_file);
+OpenFileResult
+open_file(
+ /* in */ int directory_fd,
+ /* in */ const std::vector<char> &sz_file_name,
+ /* out */ UniqueFd &opened_file,
+ /* out */ Span<const char> &opened_path
+);
+
} // namespace vostok
blob - e4e5c5bc74e604ca45c322c02d57bed199bdacdf
blob + 08c3def08a75168b755be2465e2b8845f5f517c3
--- vostok/transport.h
+++ vostok/transport.h
/** Wrap libtls for gemini protocol */
#include "utils.h"
-
-#include <vector>
#include <tls.h>
#pragma once
blob - bfc80dc82debb13758a5c46e0f023349e7870537
blob + 60749f41c58b753468d478666c6e0568f18c687b
--- vostok/utils.h
+++ vostok/utils.h
#include <cstddef>
#include <cassert>
#include <array>
+#include <vector>
#include <unistd.h>
constexpr Span(element_type (&arr)[N]) : m_p{arr}, m_count{N} {}
template <std::size_t N>
constexpr Span(const std::array<element_type, N> &arr) : m_p{arr.data()}, m_count{N} {}
+ template <typename other_element_type>
+ Span(const std::vector<other_element_type> &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;}
static_assert(N > 0, "!(N > 0)");
return Span<const char>{arr, N - 1};
}
+template <typename ElemT>
+Span<const char> cut_null(const std::vector<ElemT> &v)
+{
+ assert(v.size() > 0);
+ assert(v[v.size() - 1] == '\0');
+ return Span<const char>{v.data(), v.size() - 1};
+}
/** Smart pointer for file descriptor */
blob - d4370280c07bcdf629918760944ebc867e2974ae
blob + 35c28e6faddbc3bc9f924773c695981ddadef313
--- vostok/vostok.cc
+++ vostok/vostok.cc
#include <netinet/in.h>
#include <thread>
-#include <vector>
namespace vostok
}
UniqueFd opened_file{};
- const auto open_file_result = open_file(directory_fd, request.get_path().data(), opened_file);
+ Span<const char> 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: